Validation: Catalog tab — app portfolio with App Store links

validation-50-2026-07-17 Doc

validation fail

Verdict: FAIL

Ticket

#50 — Catalog tab: app portfolio with App Store links — Adds portfolio description header, App Store link buttons with data-turbo="false" for external navigation, app_store_url column and HTTPS validation on CatalogEntry model.
Merged PR: #84 (merge commit 9af07ff). CI fix commit: ca24329.

Environment

Production cluster, namespace intelligentstaffingsystems, URL https://intelligentstaffingsystems.ai.
Running pod image: harbor.tail5b443a.ts.net/intelligentstaffingsystems/app:93b9a79b (10 commits behind PR #84 merge). ArgoCD status: Synced / Degraded.

Tiers Executed

  • Tier 1 (Local — code inspection): Full source review of all changed files. Docker tests skipped per issue #65.
  • Tier 3 (Production): kubectl pod status, ArgoCD sync/health, endpoint curl, pipeline status.

Checks

# Criterion How Verified Result Evidence
1 Pipeline green for merge commit Woodpecker pipeline #85 (PR #84 merge) and #90 (CI fix) FAIL Pipeline #85: security + test failed. Pipeline #90: security passed, test failed (<code>minitest/mock</code> LoadError — systemic gem issue). Build-and-push SKIPPED on both.
2 New image tag propagated to pod <code>kubectl get pods -n intelligentstaffingsystems</code> FAIL Running pod uses image <code>:93b9a79b</code> (commit from before PR #84). No new image was pushed because CI failed.
3 Pod running and ready <code>kubectl get pods --all-namespaces</code> PARTIAL Old pod <code>-6d6896dd95-ls9k4</code> is Running (0 restarts, 11h). New pod <code>-8474c67bc8-nxphp</code> is Init:CrashLoopBackOff (13 restarts) due to <code>PLACEHOLDER_POSTGRES_HOST</code> DB connection error.
4 Health endpoint returns 200 <code>curl https://intelligentstaffingsystems.ai/up</code> PASS Returns HTTP 200. Root URL also returns 200. <code>/catalog</code> returns 302 (redirect to login — expected for unauthenticated).
5 Portfolio description at top of catalog page Source: <code>app/views/catalog/index.html.erb</code> lines 14-18 CODE PASS Header has <code>.catalog-intro</code> with text: "These are real apps we have built and shipped to the App Store... Everything you see here is customizable to your exact needs."
6 Description communicates target audience Source: <code>index.html.erb</code> line 17 CODE PASS Text mentions "sports program, a local shop, or a service with monthly subscribers" and "the app that runs your business."
7 Cards display with App Store link via app_store_url column Source: <code>_catalog_entry.html.erb</code> lines 25-30, migration, model CODE PASS Migration adds <code>app_store_url:string</code>. Model validates HTTPS format (<code>allow_blank: true</code>). Partial renders <code>.catalog-app-store-link</code> when <code>safe_app_store_url(entry)</code> returns a URL.
8 App Store links use <code>data-turbo="false"</code> for external navigation Source: <code>_catalog_entry.html.erb</code> line 26, <code>show.html.erb</code> line 51 CODE PASS Both index card partial and show page use <code>data: { turbo: "false" }, target: "_blank", rel: "noopener noreferrer"</code>.
9 Responsive card grid layout Source: <code>catalog.css</code> lines 114-118, 427-430 CODE PASS Mobile: <code>grid-template-columns: 1fr</code>. Desktop (600px+): <code>repeat(2, 1fr)</code>.
10 All three roles see identical content Source: <code>catalog_controller.rb</code> (no role checks), tests lines 21-37 CODE PASS Controller has no role restrictions. Tests verify lead, client, admin all get 200.
11 Detail page shows expanded description, screenshots, tech stack Source: <code>show.html.erb</code> CODE PASS Gallery section, description via <code>simple_format</code>, tech tags in sidebar, App Store link in sidebar.
12 Endpoint tests: role access (lead/client/admin 200, signed-out redirect) Source: <code>catalog_controller_test.rb</code> CODE PASS Tests at lines 8-37 cover all four cases. Additional tests for content, App Store links, data-turbo attributes.
13 Model tests: CatalogEntry validations including app_store_url Source: <code>catalog_entry_test.rb</code> CODE PASS Tests at lines 112-137: optional field, blank allowed, HTTPS accepted, non-HTTPS rejected, arbitrary text rejected.

Regression Check

  • Production root URL returns 200 — existing deployment is healthy.
  • The /up health endpoint returns 200.
  • The currently running pod (old image) has 0 restarts and has been stable for 11 hours.
  • No regression in existing deployment, but the NEW deployment attempt is CrashLooping due to database config.

Discovered Issues

  • CI test infrastructure broken — minitest/mock LoadError. Pipeline #90 test step fails with cannot load such file -- minitest/mock (LoadError). This is a systemic issue (not PR #84 specific) that blocks ALL CI pipelines from reaching build-and-push. The minitest-mock gem needs to be added to Gemfile or the Ruby 3.4 bundled gems configuration needs updating. This blocks deployment of ALL merged changes.
  • ArgoCD Degraded — PLACEHOLDER_POSTGRES_HOST. New ReplicaSet pod -8474c67bc8-nxphp crashes in init container with ActiveRecord::DatabaseConnectionError: There is an issue connecting with your hostname: PLACEHOLDER_POSTGRES_HOST. The deployment has a placeholder database host that was never replaced with the real value. This is a kustomize/secrets configuration issue in pal-e-deployments.
  • Image 10 commits behind. The running image (:93b9a79b) is from before Sprint B PRs #82, #83, #84, and the CI fix commit. None of the Sprint B features are live in production.

Failure Summary

The code implementation is correct and complete — all acceptance criteria are satisfied at the source level. However, the changes have not been deployed to production because:
  • CI pipeline fails at the test step (minitest/mock LoadError), preventing image build-and-push.
  • No new image exists in Harbor for commits after 93b9a79.
  • ArgoCD is degraded due to database connection misconfiguration in the deployment overlay.
Both discovered issues (#1 CI gem fix, #2 deployment secrets) must be resolved before any Sprint B work can be validated in production. The ticket cannot move to done until the changes are confirmed live.