# THIS YOU — Retailer Access Audit / ARKET Access Denied

**Audit target:** current THIS YOU dev code reconstructed from the latest available base + patches through V1.8 Teleport  
**Safety patch:** V1.8.1 Retailer Access Safety  
**Runtime:** PHP 7.4 / Laragon

## Executive conclusion

The available code contains multiple server-side retailer access paths that can create automation-shaped traffic from the development computer's normal public internet connection. The strongest candidates are the exact-price verifier and, historically, the V1.7.5 visual-reference materializer/headless-browser fallback.

The observed pattern — ARKET blocked on the development/home connection while the same site works over phone mobile data — is **consistent with a public-IP/WAF reputation or automation-score block**, but the code cannot prove which Akamai rule fired. There was no historical outbound retailer-request log before V1.8.1, so an exact retrospective count of ARKET requests is not available.

The architecture also needs a further change: customer-order production should not depend on live retailer page access. V1.8.1 makes the existing access safer, observable and non-aggressive, but it is a containment/safety patch rather than the final sourcing architecture.

---

## 1. What retailer requests existed in the application

### A. Frontend / normal browser

The admin contains `OPEN PRODUCT` / product links. These are normal browser navigations and therefore use the user's browser and home public IP.

There is no evidence in the current frontend of an automatic product-page crawler, generic link validator, or JavaScript loop that repeatedly opens retailer pages.

### B. PHP/backend — exact price verification

Primary code path:

```text
admin/product-first.php
→ ty_product_price_verify_fresh()
→ ty_product_price_fresh_fetch()
→ ty_product_price_http_fetch_once()
```

Before V1.8.1 this performed direct server-side GETs to exact retailer product pages.

Historical request characteristics:

```text
User-Agent:
THIS-YOU-PriceVerifier/1.0 (+human editorial verification)

Headers:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
```

Every product-page request also added a unique query parameter:

```text
__ty_price_recheck=<timestamp-random>
```

This forced every recheck to look like a unique URL/cache key.

The verifier manually followed redirects. Before V1.8.1 the redirect loop allowed up to 6 request attempts across a redirect chain.

### C. Product importer

The product-selection JSON importer itself does not scrape a retailer. It stores the candidate data and leaves it unverified.

The **subsequent A3 price recheck** is what caused live retailer page requests.

### D. Visual-reference image downloader

Code path:

```text
admin/visual-lock.php
→ ty_product_visual_reference_materialize()
→ ty_product_visual_reference_download()
```

Historically this directly downloaded official image/CDN URLs.

V1.7.5 request characteristics included:

```text
User-Agent:
Mozilla/5.0 ... Chrome/131 Safari/537.36

Headers:
Cache-Control: no-cache, no-store, max-age=0
Pragma: no-cache
Referer: exact retailer product page
```

The request was still cURL even though it advertised a browser User-Agent. It followed up to 5 redirects.

The normalizer allowed up to 6 visual references per product.

### E. V1.7.5 exact-page visual-reference discovery

If known image URLs did not produce a usable local image, V1.7.5 did this:

```text
fresh exact product-page GET
→ parse JSON-LD / og:image / img tags
→ collect up to 6 image candidates
→ download candidate images
```

Therefore one button click could create both product-page traffic and multiple asset requests.

### F. V1.7.5 headless Chrome fallback

This was the highest-risk traffic shape.

If direct image/page extraction did not produce a reference, V1.7.5 launched Chrome/Chromium with:

```text
--headless
--window-size=1440,1800
--virtual-time-budget=8000
fresh temporary user-data-dir
spoofed Chrome/131 User-Agent
```

A headless retailer page does not make only one request. The page can independently request JavaScript, CSS, analytics, fonts and many product images, potentially in parallel.

The old `FETCH / MATERIALIZE REAL REFS` action processed every selected product and could invoke this fallback per product.

### G. Playwright / scraper framework

No Playwright integration was found in the reconstructed code.

There is no separate crawler framework identified. The relevant automated paths are PHP cURL/file GETs plus the historical headless-Chrome screenshot fallback.

### H. Print renderer

The print/PDF Chromium flow primarily opens THIS YOU local pages. It is not the normal ARKET product sourcing path.

It can only hit a retailer asset if a page itself is configured to render a remote retailer URL. It is not identified as the main ARKET traffic source in this audit.

### I. Teleport importer

V1.8 Teleport does not fetch retailer pages. It imports the GPT handoff into THIS YOU and is **not** an ARKET traffic source.

### J. Custom GPT / ChatGPT web research

Custom GPT / ChatGPT web browsing is executed from OpenAI infrastructure, not from the Laragon/home connection. It therefore does not explain a block that appears specifically on the user's home public connection while mobile data still works.

---

## 2. Approximate request frequency before V1.8.1

Exact historical counts cannot be reconstructed because the application did not log outbound retailer GETs.

The code allows the following estimates.

### Price recheck

For a normal product page with no redirects:

```text
VERIFY / RECHECK PRICE
≈ 1 retailer page GET
```

For four products from the same retailer:

```text
VERIFY / RECHECK ALL PRICES
≈ 4 retailer page GETs
```

They were processed sequentially, not intentionally in parallel.

Before V1.8.1, a redirect chain could cause up to approximately 6 GETs for one product. Repeated button clicks had no cooldown or deduplication, so every click started new requests with new cache-busting URLs.

### Visual-reference materializer — V1.7.5

Per product it could:

```text
try existing image URLs (up to 6)
+
fetch exact product page
+
extract/download up to 6 image candidates
+
launch one headless product-page screenshot if still unsuccessful
```

The exact network count of a headless page load is not bounded by one HTTP request because the browser itself can load many subresources.

This path could therefore create a materially larger and more bot-like request footprint than the price verifier.

### V1.7.6+ Manual GPT path

This was already improved before the present audit:

- Manual GPT B1 does not require localhost to scrape the exact retailer page.
- `TRY LOCAL CACHE (OPTIONAL)` only tries known direct image URLs.
- It no longer invokes the slow screenshot fallback from that admin action.

However, multiple known direct image URLs could still be downloaded from the retailer/CDN if the optional cache button was clicked.

---

## 3. Retry and failure behavior before V1.8.1

### Price verifier

A 403 on the current URL did not recursively retry that same URL. It failed the product check.

However:

- there was no retailer-wide backoff;
- there was no cooldown;
- there was no successful-request deduplication;
- repeated admin clicks caused new network requests immediately;
- every request got a unique synthetic query parameter;
- a redirect chain could add requests.

So there was no infinite internal loop, but repeated human/UI actions could behave like repeated automated probes.

### Visual-reference flow

Failures were more expensive:

```text
image failure
→ exact page fetch
→ more image candidates
→ more image downloads
→ headless Chrome page load
```

This means a failed direct request could intentionally trigger **additional automatic requests**, exactly the behavior that should be avoided against a WAF-blocked retailer.

---

## 4. What most likely contributed to the ARKET block

### Confirmed from code

The system generated automation-shaped retailer traffic using:

- PHP cURL from the home/development connection;
- a dedicated bot-like price-verifier User-Agent;
- unique `__ty_price_recheck` query parameters;
- explicit no-cache/no-store headers;
- repeated live exact-page verification;
- no retailer rate limit or cooldown;
- no WAF backoff;
- image downloads from retailer/CDN URLs;
- historically, fresh-profile headless Chrome fallback after failures.

### Inference

It is plausible that one or a combination of these patterns increased ARKET/Akamai's automation/risk score for the public home IP.

Especially suspicious from a WAF perspective are:

```text
same public IP
+
server-side cURL fingerprint
+
non-browser/bot UA or UA/TLS mismatch
+
unique query strings
+
no-cache requests
+
several exact product/image accesses in a short period
+
failure → more automated fallback traffic
+
fresh headless-browser profiles
```

Because the phone works over mobile data, the incident is consistent with a public-IP-specific or connection-specific decision rather than a globally broken ARKET page.

This remains an inference. The exact Akamai rule, reputation signal or block scope is not visible from THIS YOU code.

---

## 5. V1.8.1 safeguards

V1.8.1 introduces one shared `lib/retailer-access.php` safety layer for server-side retailer GETs.

### Central outbound logging

New JSONL log:

```text
storage/logs/retailer-requests.jsonl
```

Fields include:

```text
retailer
request_host
url
timestamp
source_job
http_status
attempt_number
response_time_ms
cache_hit
event
error
backoff_until
user_agent
```

New admin screen:

```text
Admin → Retailer Log
```

It shows current host backoff state and recent network/cache/blocked events.

### Per-retailer pacing

Default:

```text
minimum 3 seconds between server-side network requests to the same retailer bucket
```

Common asset hosts such as `media.arket.com` / `cdn.arket.com` are conservatively grouped with the retailer host where possible.

### No parallel bursts

V1.8.1 adds a per-retailer cross-process file lock using `flock()`.

Concurrent PHP requests targeting the same retailer are serialized. A second PHP process waits for the retailer lock rather than firing a parallel request.

### Deduplication/cache

Default successful-response TTLs:

```text
product/page request: 300 seconds
visual asset: 86400 seconds
```

An identical request during that period reuses the stored response instead of hitting the retailer again.

The cache is explicitly a safety/dedup layer. Long-term product freshness must be managed by the future sourcing/revalidation pipeline rather than by repeatedly scraping during an order.

### No synthetic cache-busting URL

Removed:

```text
__ty_price_recheck=...
```

Requests use the canonical retailer URL.

### Honest User-Agent

Server-side cURL no longer pretends to be Chrome.

Default:

```text
THIS-YOU-RetailerMetadata/1.1 (+editorial product verification)
```

This is not a bypass mechanism. It makes the client behavior explicit.

### Backoff

A failed request is not automatically retried.

Default future-request backoff:

```text
403 / 429: 15 minutes starting backoff
network / 5xx: 60 seconds starting backoff
repeated failures: exponential doubling
maximum: 6 hours
```

During backoff, calls fail locally and log `blocked_backoff`; no request is sent to the retailer.

### Retailer disable switch

Config supports:

```php
'retailer_access' => array(
    'disabled_hosts' => array(
        'arket.com' => true
    )
)
```

When disabled, THIS YOU logs the blocked attempt but sends no network request.

### Timeout handling

Default central request timeouts are shorter/conservative:

```text
connect: 5 s
request: 12 s
```

Callers may set a bounded value, but there are no infinite waits.

### Redirect limit

Price page redirects are reduced to a bounded chain. Redirects do not turn into an unlimited retry mechanism.

### Automatic headless retailer screenshots disabled

V1.8.1 hard-disables the automatic retailer-page screenshot fallback.

Reason: a browser page load can fan out into many subresource requests and is inappropriate inside customer-order production.

Alternatives:

```text
pre-sourced/cached official asset
Manual GPT remote inspection
human-uploaded exact product reference
```

No WAF circumvention is added.

---

## 6. Does the sourcing architecture need to change?

**Yes.**

V1.8.1 prevents the current implementation from behaving aggressively, but the current A3 workflow still has a live retailer-verification concept attached to a reader/chapter production flow.

That is too fragile for scale.

The correct target architecture is:

```text
RETAILER SOURCING / REVALIDATION
        ↓
THIS YOU PRODUCT CATALOG + SNAPSHOT CACHE
        ↓
PRODUCT EDITORIAL APPROVAL
        ↓
CUSTOMER ORDER
        ↓
AI STYLING / HERO / FIDELITY USING STORED DATA + STORED VISUAL ASSETS
```

not:

```text
CUSTOMER ORDER
→ live retailer page
→ live image scraping
→ HERO
```

### Recommended future product-cache entity

A global product record/snapshot should store, where appropriate:

```text
retailer
canonical URL
retailer product ID / SKU
product name
category
exact colour / variant
regular/base price
currency
availability state
approved local reference images
reference provenance
visual lock / feature map
last checked timestamp
verification status/confidence
```

Reader-specific `user_issue_products` should reference/freeze an approved product snapshot rather than becoming the primary place where retailer data is discovered and verified.

### Revalidation becomes asynchronous/editorial

Retailer access should happen in a sourcing/revalidation context, never because a customer order is waiting for a page to render.

If a retailer is unavailable:

```text
existing order continues with its approved frozen snapshot
availability may be marked stale
no silent product substitution
replacement is a separate editorial action
```

Approved product visual references are intentionally cacheable/frozen because visual consistency between approval and HERO generation is desirable.

Regular price/availability can be revalidated separately on a controlled schedule or by editorial action.

---

## 7. What V1.8.1 does not claim

V1.8.1 does **not**:

- bypass Akamai;
- rotate IP addresses;
- spoof residential browsers;
- solve CAPTCHAs;
- use proxy pools;
- aggressively retry 403s;
- guarantee ARKET will unblock the current public IP;
- reconstruct historical outbound traffic that was never logged.

The goal is safety, observability and graceful retailer failure.

---

## 8. Recommended immediate action for ARKET

While the home connection is currently blocked:

1. Do not repeatedly test ARKET from THIS YOU server-side tools.
2. Install V1.8.1 before any further retailer automation testing.
3. Optionally set `arket.com` in `retailer_access.disabled_hosts` while the block is active.
4. Use the already stored/GPT-provided product metadata and visual references for work already in progress.
5. Inspect `Admin → Retailer Log` for all future server-side access.
6. Move next to the global product catalog/cache architecture before scaling customer orders.

---

## 9. Audit answer against requested checklist

| Requested check | Finding |
|---|---|
| Requests to ARKET | Exact historical count unavailable; code paths capable of exact product-page GETs, direct image GETs, and historical headless page loads identified. |
| Frontend/browser | Manual product links only; no automatic frontend crawler found. |
| PHP/backend | Yes — exact-price verifier and visual image downloader. |
| Scraper | No separate scraper framework found. |
| Playwright | Not found. |
| Headless browser | Yes historically — Chrome/Chromium screenshot fallback in V1.7.5. |
| Product importer | Import itself no; A3 verification after import performs retailer requests. |
| Image downloader | Yes. |
| Link validator | No generic live link validator found. |
| AI sourcing | Custom GPT browsing does not originate from localhost/home IP. |
| Frequency | Price: ~1 page GET/product normally; `recheck all` ~N products; historical visual flow could create many more requests. |
| Concurrent requests | No intentional PHP batch concurrency; historical headless page itself can fan out. V1.8.1 adds explicit per-retailer process serialization. |
| Automatic asset downloads | Yes historically and still optional for already-known references, now paced/cached/logged. |
| User-Agent | Historical bot UA for price; historical Chrome-spoofed UA for cURL images; V1.8.1 uses honest metadata UA. |
| Retry loops | No infinite loop found; bounded redirects existed. Repeated UI clicks were not deduped before V1.8.1. |
| Failure → more requests | Yes historically in visual fallback; V1.8.1 disables automatic page/screenshot escalation and adds backoff. |
| Retailer hard dependency | Still conceptually present in A3; should be removed by next product-cache architecture phase. |

---

## Final verdict

The localhost/dev tooling **could plausibly have contributed to the ARKET block**, especially the combination of fresh no-cache price checks and the earlier visual-reference/headless-browser fallback. There is insufficient historical logging to claim that it definitely did.

V1.8.1 removes the riskiest behavior and makes all future server-side retailer requests paced, serialized, cached/deduplicated, logged, backoff-aware and kill-switchable.

The final scalable fix is architectural: **source products first, freeze/cache them inside THIS YOU, then produce customer magazines from THIS YOU's own approved product snapshots and local visual assets.**
