Date: 2026-02-03
Responsibilities
- Ad model definitions, validation, parsing, and normalization.
- Ad selection policy and display eligibility.
Key modules/files (current locations)
- Domain types embedded in UI component: components/RandomAd.vue
Boundary violations
- Domain types and parsing logic live in a UI component (not reusable, tightly coupled to rendering).
- API response parsing and mapping are coupled to view state.
High-risk couplings / failure points
parseInton potentially empty strings can yieldNaNand propagate to UI logic.- No validation of required fields before rendering (e.g., missing
href,imagePath). - Ad type handling is stringly-typed and scattered (e.g., "MochahostBanner", "ImageAd").
Responsibilities
- Runtime configuration, external API access, and network concerns (CORS, fetch).
Key modules/files
- Runtime config: nuxt.config.ts
- CORS handling: previously implemented via server middleware (server/middleware/cors-ivan.ts) — middleware folder removed; ensure hosting or CDN static headers provide appropriate CORS rules
- API access currently embedded in UI: components/RandomAd.vue
Boundary violations
$fetchand URL construction are in the UI component instead of a dedicated infrastructure/composable layer.- Runtime config access inside the UI component.
High-risk couplings / failure points
- Missing or empty
NUXT_PUBLIC_ADS_SERVERyields invalid requests with no fallback. - Note: server middleware was removed and therefore CORS must be enforced by the hosting layer or static headers; verify CDN/host config to avoid production mismatches.
- No retry, timeout, or error classification for ad server failures.
Responsibilities
- UI composition and rendering, layout, interactivity.
Key modules/files
- App shell: app.vue
- Ad display and conditional rendering: components/RandomAd.vue
- Provider-specific components: components/Amazon/Banner.vue, components/Google/AdSense.vue, components/Mochahost/Banner.vue
Boundary violations
- UI component handles data fetching, response parsing, postMessage messaging, and model logic.
High-risk couplings / failure points
window.parent.postMessageis called to*, with no origin filtering.notifyParentOfAdDimensionsruns before validating ad display readiness.- Query params are forwarded verbatim to the backend, making behavior implicit and hard to reason about.
-
Fat component / mixed concerns
- Impact: Hard to test, harder to reuse, brittle to API changes.
- Refactor: Extract data fetching + parsing into
composables/useAdService.ts; extract domain types todomain/ads/types.ts.
-
Stringly-typed domain
- Impact: Fragile branching, easy to break with new ad types.
- Refactor: Introduce a discriminated union with explicit validators; map response into a normalized
Admodel.
-
Leaky infrastructure concerns in UI
- Impact: UI breaks when config is missing or API changes.
- Refactor: Centralize runtime config validation in a composable; return typed errors.
-
Implicit side effects
- Impact: PostMessage to
*may expose data to untrusted contexts. - Refactor: Restrict allowed origins via config; gate calls by known
origin.
- Impact: PostMessage to
-
Unvalidated external data
- Impact: Rendering failures or silent UI breakage.
- Refactor: Validate API responses (e.g., schema validation) before mapping.
-
Move data fetching + parsing into a composable
- Effort: Medium
- Risk reduction: High
- Targets: components/RandomAd.vue
-
Define domain models in a dedicated module
- Effort: Low
- Risk reduction: High
- Targets: new
domain/ads/module; update components/RandomAd.vue
-
Validate runtime config and API response
- Effort: Medium
- Risk reduction: High
- Targets: nuxt.config.ts, new composable
-
Origin-locked postMessage
- Effort: Medium
- Risk reduction: Medium
- Targets: components/RandomAd.vue, config in nuxt.config.ts
-
Explicit error types and UI fallback
- Effort: Medium
- Risk reduction: Medium
- Targets: components/RandomAd.vue
- Query param allowlist
- Effort: Low
- Risk reduction: Low
- Targets: components/RandomAd.vue