V1 Web PWA · Surface walkthrough

AAA Upgrade · Continue in Yemaya AAA Studio

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked + e2e-covered
9sections5 minread

On this page

Context. surface customer · domain system · route /aaa-upgrade · auth signed-in · source apps/oshun/web/src/app/aaa-upgrade/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; content re-verified 2026-06-03 against current source; route-state, CTA target, source sanitisation, anonymous redirect, and touch-target evidence refreshed 2026-06-27 in apps/oshun/web/e2e/aaa-upgrade-entitlement-bounce.spec.ts; reduced-motion static state, route-local CTA focus-visible styling, link count, and telemetry absence added 2026-06-27; view and CTA telemetry added 2026-06-30; mobile standalone no-overflow/touch-target proof and real service-worker offline document replay added 2026-07-02

Purpose#

Yemaya AAA-tier upgrade disclosure (§24.11). Users with the aaa-creator or operator-admin entitlement who hit an AAA-only route on the contemplative product are routed here. Users without the entitlement are hard-blocked by middleware before they reach this page.

The page is disclosure copy + two CTAs: continue into Yemaya AAA Studio (the destination product) or back to the gallery. There is no upgrade purchase flow here — the entitlement is presumed to already exist.

Entry points#

  • Middleware bounce: AAA-only contemplative routes redirect users carrying the right entitlement to /aaa-upgrade?from=<orig> where from records the source path
  • Direct URL — bookmarkable; gating is enforced upstream by middleware
  • Studio navigation links pointing back to this disclosure

Layout regions#

page.tsx is a server async component reading searchParams to extract a sanitised from string. Renders a single inline-styled <main> (no shell chrome) with data-testid="aaa-upgrade-page":

  • Title (h1): "This surface lives in Yemaya AAA Studio"
  • Body paragraph: "Oshun keeps the contemplative product curated — raw graph editors, LoRA training, model merging, and the rest of the AAA-tier generation surfaces live in Yemaya AAA Studio. Your entitlement includes access."
  • "You arrived from" line (conditional): rendered when from is a string; shows <code data-testid="aaa-upgrade-from">{from}</code>
  • Action row:
    • Primary <Link href="/studio/yemaya/studio-web" data-action="open-yemaya">: "Continue in Yemaya Studio" — uses --lilith-terracotta background, white text. When a safe from is present, the link appends ?from=<encoded /studio/isis/... path>. Click dispatches aaa_upgrade_open_yemaya_clicked.
    • Secondary <Link href="/studio/generation-gallery" data-action="back-to-gallery">: "Back to gallery" — paper border, ink colour. Click dispatches aaa_upgrade_back_to_gallery_clicked.

Layout uses inline styles (no design-system primitives): grid gap 16, padding 40, max-width 720, centred.

States#

  • Default (no from) — title + body + action row; no "arrived from" line
  • With ?from=<path> — extra line surfaces the origin route as <code>
  • from is array — coerced to null by the type guard (typeof fromRaw === 'string' ? fromRaw : null)
  • Anonymous user — middleware redirects to /welcome before reaching the page
  • Signed-in user without AAA entitlement on an AAA-only source route — middleware hard-blocks before this page renders
  • Reduced motion — no CSS keyframe animation is present on this surface under prefers-reduced-motion: reduce
  • Offline — real Chromium service-worker warm/reload caches /aaa-upgrade; context.setOffline(true) replays the disclosure document from the service worker with no generic offline fallback card
  • Standalone PWA — mocked home-screen relaunch at 390×844 preserves display-mode: standalone, renders both CTAs, preserves the safe from=/studio/isis/gpu-worker echo, keeps both CTAs ≥44px, and has no horizontal overflow

Interactions#

Title / body#

  • Non-interactive copy

Action row#

  • "Continue in Yemaya Studio" (Link, data-action="open-yemaya")
    • Function: navigates to /studio/yemaya/studio-web and preserves only a safe internal /studio/isis/... source path as from
    • Keyboard: Tab → Enter activates
    • Focus: route-local :focus-visible outline is visible when focused
    • Touch target: padded 10×16; verified ≥ 44px in browser layout
    • Visual: --lilith-terracotta background, white text
  • "Back to gallery" (Link, data-action="back-to-gallery")
    • Function: navigates to /studio/generation-gallery
    • Keyboard: Tab → Enter activates
    • Focus: route-local :focus-visible outline is visible when focused
    • Touch target: padded 10×16; verified ≥ 44px in browser layout

Data & contracts#

  • Reads:
    • searchParams.from?: string | string[] | undefined
  • Writes: none
  • Telemetry: the client action row dispatches aaa_upgrade_viewed on mount, then aaa_upgrade_open_yemaya_clicked or aaa_upgrade_back_to_gallery_clicked for the two CTAs. Payloads include surface: 'aaa_upgrade', the allowlisted sourcePath or null, and the fixed destination for click events.
  • Realtime: none
  • Caching: not explicitly cached
  • Auth/role check: middleware enforces aaa-creator / operator-admin entitlement upstream; the page itself does not re-check
  • Metadata: title: 'Continue in Yemaya AAA Studio', description: 'Yemaya AAA Studio hosts the professional generation surfaces.', alternates.canonical: '/aaa-upgrade'

Cross-references#

  • Shell auth + entitlements: shell/04-auth-session.md
  • Destination route: /studio/yemaya/studio-web (the primary "open-yemaya" CTA links directly to Yemaya Studio Web, not /studio or /welcome/yemaya)
  • Studio gallery: /studio/generation-gallery (see studio/)
  • Component sources:
    • apps/oshun/web/src/app/aaa-upgrade/page.tsx
    • apps/oshun/web/src/app/aaa-upgrade/AaaUpgradeActions.tsx
    • apps/oshun/web/src/analytics/aaaUpgradeTelemetry.ts

Automated coverage#

  • apps/oshun/web/e2e/aaa-upgrade-entitlement-bounce.spec.ts
    • AAA aaa-creator boundary bounce to /aaa-upgrade?from=<source>, rendered source echo, and CTA href with the encoded safe source
    • Contemplative and anonymous/malformed sessions hard-blocked at AAA-only source routes without leaking /aaa-upgrade
    • operator-admin boundary bounce
    • Hostile external from dropped, with no external links rendered
    • Direct signed-in /aaa-upgrade default state, repeated from values dropped, anonymous direct page redirect, both CTA touch targets, visible focus outlines, exactly two page links, no telemetry hook attributes, aaa_upgrade_viewed, both CTA click telemetry events, and zero keyframed descendants under reduced motion
    • Mobile standalone relaunch with safe from propagation, no horizontal overflow, and ≥44px CTAs; real service-worker offline document replay of the warmed /aaa-upgrade page
  • apps/oshun/web/e2e/entitlements-aaa-bff.spec.ts verifies the real BFF entitlement resolver contract returns /aaa-upgrade as the upgrade URL.
  • apps/oshun/web/src/app/__tests__/aaa-upgrade.test.tsx covers component-level valid-source propagation and hostile-source suppression.

Open questions / known gaps#

  • Confirm the exact middleware rule that lands users here (the legacy /studio/isis/* tree bounces AAA and operator sessions to this disclosure and hard-blocks contemplative/anonymous access)
  • The page is described as an "upgrade flow" but doesn't include a purchase / entitlement-grant step — confirm the user-journey assumption (entitlement is pre-existing; this page is disclosure + continuation only)
  • CTAs use raw <Link> not design-system buttons; automated evidence now covers touch targets and route-local visible focus outlines
  • View and CTA telemetry are emitted without raw telemetry/analytics attributes in the DOM. aaa-upgrade-entitlement-bounce.spec.ts captures aaa_upgrade_viewed, aaa_upgrade_open_yemaya_clicked, and aaa_upgrade_back_to_gallery_clicked.
  • from is rendered as <code> text after route allowlisting; hostile external URLs and repeated values are dropped rather than echoed or linked
  • Visual chrome doesn't match Lilith manuscript register used by other system pages; inline styles only