# PhpStorm Agent Prompt Pack: Public Retest Corrections
Run these prompts in order, one task at a time. They address the live retest on
2026-08-28; do not repeat already completed work unless a prompt identifies a
regression.
## Shared instruction block
Prepend this block to every prompt:
> Work only on the relevant public Zapazime route, view, translation,
> configuration, deployment documentation, and focused tests. Preserve unrelated
> working-tree changes. Inspect existing routing and production behavior before
> editing. Do not hide a failure with a broad catch block, make unpublished or
> inactive venues public, disable CSRF/authorization, or invent listing data.
> Run tests using PHP 8.3+ only. At the end report root cause, changed files,
> exact tests run, deployment/cache commands, and remaining risk.
---
## 1. Fix `/venue/{id}` without weakening public visibility
> Repair the public venue-detail compatibility bug. Homepage and deal cards link
> to `/venue/{id}` when a venue lacks a slug, but the `/venue/{slug}` controller
> currently searches only the `slug` column. A separate `/venue-id/{id}` route was
> added, but it does not repair the links already rendered by the site and may
> expose inactive/private venues. Implement one deliberate canonical strategy:
> either support a numeric value safely within `/venue/{identifier}` and redirect
> to a slug URL where available, or update all producers to emit a dedicated,
> stable ID URL. Apply explicit numeric constraints and route ordering so no
> existing slugs collide. Use one shared public-publication scope for slug and ID
> lookup; absent, inactive, unpublished, deleted, or unauthorized/private venues
> must return 404.
Acceptance criteria:
- `/venue/1` works for an eligible published venue and never returns 500.
- Slug URLs remain supported and are canonical for venues with slugs.
- Numeric identifiers cannot accidentally match/reserve a slug route incorrectly.
- Inactive/private/missing venues return 404 with no existence leakage.
- Homepage, locations, deals, favourites, similar venues, canonical tags, and
API-generated public links use the same URL strategy.
- Feature tests cover numeric ID, slug, redirect/canonical behaviour, missing,
inactive and private cases.
## 2. Diagnose and restore Gift Cards end-to-end at the page boundary
> Diagnose the live HTTP failure on `/gift-cards`. Reproduce the exception with
> production-like configuration and inspect the controller, `web.gift-cards`
> Blade view, product query, route names, assets, translations and any supporting
> data assumptions. Fix the root cause rather than wrapping the view in a generic
> exception handler. If gift cards are not a complete and enabled product, remove
> every public Gift Cards link and CTA instead of displaying a broken page. Do not
> submit an order or payment; use isolated tests/sandbox fixtures only.
Acceptance criteria:
- Enabled gift-card catalogue returns 200 for an anonymous visitor.
- Empty/unconfigured catalogue has an intentional, safe state or the feature is
absent from navigation.
- Page rendering does not require optional data that can be null.
- Cart/checkout entry links have declared routes; no purchase is created by tests.
- Tests cover enabled, empty/unconfigured, unavailable and navigation states.
## 3. Repair hotel category taxonomy and search-result integrity
> Fix the public hotel discovery mismatch. `/locations?type=rentals&category=hotel`
> renders but has no venue links even though the product shows hotel-related venue
> content elsewhere. Trace the request category slug through navigation metadata,
> `Category` records, `WebController` filters, venue fields/types, publication
> scope and search view. Define a canonical hotel taxonomy and migrate/map legacy
> values safely. Do not broaden the query to show unrelated rentals or private
> inventory merely to avoid an empty state.
Acceptance criteria:
- Eligible published hotels appear in the Hotel category search.
- The menu count, location result count and actual cards agree.
- A genuinely empty market gets a clear, localized empty state.
- Filters preserve type/category/date/guest context into the venue page.
- Tests cover matching hotel, non-hotel rental, inactive/unpublished venue and
empty-result scenarios.
## 4. Finish and deploy Bulgarian localization fixes
> Complete the public Bulgarian localization pass. Production still displays
> `All locations`, `Terms & Conditions`, and `Събитиенни пространства`, although
> some local translation changes exist. Identify every source of each rendered
> string: translation key, hard-coded Blade copy, cached language file, and
> deployed release state. Use canonical keys with BG and EN translations; do not
> change the site locale to conceal missing translations. Fix the typo as
> `Събитийни пространства` after confirming the approved Bulgarian wording.
Acceptance criteria:
- BG homepage/header/footer/category UI contains none of the three reported
strings.
- EN output remains coherent and does not contain Bulgarian strings.
- Translation cache/config/view cache commands are documented and run as part of
the deployment plan.
- A focused feature/render test asserts the BG and EN labels.
## 5. Replace generic app-store destinations with truthful configuration
> Audit public app-store CTAs. The previous `#` placeholders were replaced in
> local code with generic `apps.apple.com` and `play.google.com` homepages. Decide
> whether Zapazime has released iOS/Android apps. If so, introduce configuration
> backed by approved, product-specific App Store and Google Play URLs and render
> the CTAs only when each URL is configured. If not, hide both CTAs and remove
> related promotional copy. Do not advertise a nonexistent mobile app.
Acceptance criteria:
- Every visible store CTA resolves to the verified Zapazime product listing.
- No visible CTA uses `#`, a generic storefront, or an unconfigured URL.
- Tests cover both configured and unconfigured feature states.
## 6. Make production error safety testable and correct
> Strengthen production-error handling verification. The current test checks a
> non-existent route (a 404), not a forced 500, and merely setting `app.env` does
> not necessarily prove `app.debug` is disabled. Add a test-only route or another
> isolated mechanism that throws a controlled exception, then assert that a
> production-mode anonymous response is a generic 500 with a correlation/reference
> ID and contains no framework diagnostics, session/cookie values, SQL/query
> details or debug toolbar. Keep local debug behavior explicit and ensure the
> exception handler does not itself leak messages.
Acceptance criteria:
- The test genuinely exercises the 500 renderer.
- Production debug false is enforced through deployment environment/config, not
assumed from `APP_ENV` alone.
- JSON and HTML error responses are both safe.
- Errors are logged server-side with a reference ID that support can use.
## 7. Establish a PHP 8.3+ local/CI verification gate and deploy safely
> The public-route tests cannot currently run because the local CLI is PHP 8.2.12
> while Composer dependencies require PHP 8.3+. Configure the project’s documented
> local and CI test command to use PHP 8.3+ without altering Composer platform
> requirements or bypassing `platform_check.php`. Then run the focused public
> suite and a complete route smoke test. Prepare a deployment checklist that
> includes schema state, release artifact, `APP_DEBUG=false`, cache refresh,
> worker restart where applicable, and a post-deploy anonymous smoke check for
> homepage, a known venue, Gift Cards, Blog, hotel search, legal pages, and 404/500
> safety.
Acceptance criteria:
- `php artisan test tests/Feature/PublicRoutesTest.php
tests/Feature/ProductionErrorHandlingTest.php` runs with PHP 8.3+ and passes.
- CI uses the same supported PHP major/minor version.
- No developer changes Composer requirements or suppresses runtime platform
validation to make the test pass.
- Production deployment has a documented rollback and post-deploy smoke gate.