Commit Graph

158 Commits

Author SHA1 Message Date
Jordan Ritter 7f9b63b069 fix(showcase/shell): clamp profile-client file-list when collapsed 2026-06-11 16:15:13 -07:00
Jordan Ritter 6dea8ad764 style(showcase): apply oxfmt to SU shell-runtime-urls follow-up files
Pure prettier-style rewrite (line-wrapping, single-line collapses, multi-
line callback indentation). No semantic changes — confirmed via tsc clean,
oxlint clean, vitest 235/235 pass in showcase/shell.

Touched files:
- showcase/scripts/__tests__/generate-registry-pattern.test.ts
- showcase/scripts/generate-registry.ts
- showcase/shell/src/lib/backend-url.ts
- showcase/shell/src/lib/backend-url.test.ts
- showcase/shell/src/lib/docs-redirects.test.ts
- showcase/shell/src/lib/local-backends-env.test.ts
- showcase/shell/src/lib/runtime-config.ts
- showcase/shell/src/lib/runtime-config.test.ts
- showcase/shell/src/lib/runtime-url-wiring.test.ts
- showcase/shell/src/middleware.ts
- showcase/shell/src/middleware.test.ts
- showcase/shell/vitest.global-setup.ts
2026-06-11 14:02:36 -07:00
Jordan Ritter 8e427bbc0a fix(showcase): final-round backend-pattern + POSTHOG + table + script-side parity (SU7-F1/F2/F3)
SU7-F1 — backend host pattern hardening:
- F1.1  Reject bare trailing ?/# in the backend host pattern
- F1.2  Strip internal tab/CR/LF from the backend host pattern
- F1.3  Warn when ignoring an empty-string local backend override
- F1.4  Reject empty-userinfo @ in the backend host pattern authority
- F1.5  Keep __proto__ keys as data in local-backend maps
- F1.6  Commit the local-backends memo key only after the value computes
- F1.7  Trim local backend overrides before validation and name the real
        rejection
- F1.8  Honest FATAL when the pattern host is a stray scheme fragment
- F1.9  Canonicalize the pattern authority for parity with the override
        path
- F1.10 Acknowledge the staging-to-prod fail-open in the pattern fallback
- F1.11 Harden backend-url/local-backends-env test hygiene

SU7-F2 — runtime-config & client-config edge cases:
- F2.1  Branch POSTHOG_HOST rejection reasons (scheme/degenerate/parse-
        failure) instead of the catch-all mislabel
- F2.2  Reject loopback BASE_URL/DOCS_HOST in production instead of the
        silent http:// prepend
- F2.3  Key the DOCS_HOST fallback once-guard on (mode, shellHost, value)
        and mode-prefix all value-only guard keys
- F2.4  Reject a present-but-empty posthogKey in the client config reader
- F2.5  Drop the trailing slash from SSR_PLACEHOLDER_URL for structural
        parity with server values
- F2.6  Attribute the DOCS_HOST slash-strip to readDocsHost itself
- F2.7  Normalize trailing-dot FQDN spellings in the docs self-host loop
        guard (both compare sides)
- F2.8  Harden console spies to capture all log args; pin the full all-env
        config shape; converge SSR simulation on vi.stubGlobal

SU7-F3 — script-side parity, table classification & test isolation:
- F3 #1  Handle a missing reference integration per the error contract
- F3 #2  Port the runtime backend-host-pattern normalization into the
         generator — scheme/trailing-slash strip, degenerate fallback,
         NEXT_PUBLIC fallback
- F3 #3  Treat non-mapping manifest parses (empty/null/scalar/array YAML)
         as validation errors, not TypeErrors
- F3 #4  Label a missing/unreadable constraints.yaml per the stderr+exit(1)
         error contract
- F3 #5  Align atomic-write tmp naming with the test harness straggler-
         sweep convention; guard main() on direct invocation
- F3 #6  Correct the determineCellStatus unshipped docstring; replace
         stale hardcoded cell counts with formulas
- F3 #7  Isolate the pattern suite on a per-suite tmpdir harness; snapshot
         the generator's full write set
- F3 #8  Classify discarded duplicate wildcards as duplicates — hoist the
         owner check above the destination warns
- F3 #9  Reject a root ("/") EXACT seo-redirect source — homepage-hijack
         twin of the root-wildcard guard
- F3 #10 Reject seo-redirect entries with non-printable-ASCII source/
         destination — close the silent-dead-entry class
- F3 #11 Strip trailing slashes in normalizePosthogHost before the scheme
         test
- F3 #12 Message-filter the empty-slug-set error count; pin the single
         matcher entry
2026-06-11 14:01:15 -07:00
Jordan Ritter 4f9f5dba4c fix(showcase/shell): docs-host robustness, builder & matcher hardening (SU2-stragglers + SU5 + SU6-A/B)
Round-by-round CR convergence covering the redirect builder, the middleware
matcher, the docs-host self-loop guard, and the runtime-config env readers.

Highlights:
- Clear module-load warns after fresh middleware import
- Validate SET BASE_URL values (scheme-less/degenerate/garbage) with
  sentinel fallback + once-guarded FATAL log
- Normalize path/query/fragment-bearing DOCS_HOST to origin; reject
  non-http(s) schemes; branch rejection reasons
- Harden POSTHOG_HOST (degenerate-host/scheme rejection); expose
  posthogKey via readEnvPair semantics
- Reject a DOCS_HOST equal to the shell's own host (redirect-loop guard,
  authority compare)
- Warn on missing local-ports.json under SHOWCASE_LOCAL=1 and validate
  TCP port range; extract helper for tests
- backend-url hardening — slug charset guard, frozen local-backends memo,
  pattern path-segment warn, local-override URL validation
- Client config fail-loud covers all four URL fields with type checks
- Make RuntimeConfig.posthogKey optional — absence is a valid state, not
  a wiring bug
- Drop R15/R17 and guard /integrations from SEO redirects
- Dedup duplicate wildcard prefixes with first-match-wins warn
- Validate malformed SEO entries at lookup-build time
- Restore case-insensitive redirect matching parity
- Normalize trailing slashes before redirect matching
- Keep the framework segment on F13, pin MG3 case fix
- Read posthogKey from runtime config in middleware, not raw process.env
- Fall back to the default backend host pattern for degenerate values
- Disable docs redirects when the default fallback collides with the
  shell host
- Bring validateBaseUrl to parity with its sibling readers
- Strip query/fragment from POSTHOG_HOST while keeping reverse-proxy paths
- Restrict local backend overrides to http(s) URLs
- Add server-only guard to runtime-config
- Harden localBackendsEnv failure posture
- Hoist /integrations namespace guard above the docs-host redirect
- Validate seo-redirect sources and cross-kind shadowing in
  buildRedirectLookup
- Unify slash normalization for middleware matching
- Lowercase-normalize REGISTRY_FRAMEWORK_SLUGS at construction
- Escalate missing POSTHOG_KEY to console.error in production
- Skip all redirect steps when docs redirects are disabled (sentinel
  consumer)
- Reject userinfo credentials in DOCS_HOST, POSTHOG_HOST, and the backend
  host pattern
- Branch dev-vs-prod logging in readDocsHost and fatalPatternOnce
- Prepend http:// (not https://) to scheme-less loopback hosts
- Round-5 micro-finding batch across the URL config libs

SU5-A1..A7 — registry safety, // reject, builder lint batch (case-
insensitive :path*, same-destination twin allowlist, original-case
divergence remainder), matcher api boundary, generator+vitest infra, test
hygiene + empty docs-host guard, comment batch.

SU6-A1..A6 — reject miscased :path* tokens, warn on tokenless wildcards,
normalize redirect-destination comparisons like request time, reject
destinations containing "//", surface missing POSTHOG_KEY at config-
resolution time, compile matcher harness like Next's runtime, type
parse/tokensToRegexp in the path-to-regexp shim, keep buildRedirectLookup
JSDoc attached.

SU6-B1..B7 — reject query/fragment/userinfo in pattern and local-override
URL gates, return parsed-normalized URL form from validation success
paths, distinguish unset/blank/padded SHOWCASE_LOCAL states, warn when
SHOWCASE_LOCAL is set to a value other than 1, validate {slug} placeholder
in generate-registry, mirror middleware drop semantics in the wiring
test's registry re-derivation, pin the noStore spy and calls to one fresh
module instance in the Edge-path test.
2026-06-11 14:00:50 -07:00
Jordan Ritter b28a1dc494 fix(showcase/shell): runtime-config + backend-url env-hardening; redirect builder safety (SU2-A/B + CR2-C)
SU2-B series — runtime-config / backend-url env robustness:
- Correct the Edge-safety story in runtime-config (SU2-B1)
- Stop per-request FATAL-CONFIG spam for unset BASE_URL (SU2-B2)
- Prepend https:// to a scheme-less POSTHOG_HOST (SU2-B3)
- Trim whitespace paste artifacts in env values and host patterns (SU2-B4)
- Memoize parseLocalBackends and warn once per value (SU2-B5)
- Make {slug} substitution immune to $-patterns (SU2-B6)
- Harden the client runtime-config reader (SU2-B7)
- runtime-config hardening batch (SU2-B8)
- Validate local-ports.json before baking NEXT_PUBLIC_LOCAL_BACKENDS (SU2-B9)
- test: warn-once assertions retry-safe; stop console leaks (SU2-B10)

CR2-C series — test infrastructure:
- Generate registry.json in a vitest globalSetup (CR2-C1)
- Stop ambient POSTHOG_KEY firing real fetches in middleware tests (CR2-C2)
- Assert the production slug set, not a re-derivation (CR2-C3)
- Make the registry generator subprocess robust (CR2-C4)
- Middleware/wiring test hygiene batch (CR2-C5)

SU2-A series — redirect-layer & PostHog capture:
- Stop $-pattern expansion in wildcard redirect substitution (SU2-A1)
- Surface PostHog capture failures once per failure class (SU2-A2)
- Duplicate exact redirect sources are first-match-wins (SU2-A3)
- Resolve runtime config once per redirected request (SU2-A4)
- Include destination host in seo_redirect capture (SU2-A5)
- Normalize scheme-less POSTHOG_HOST at the capture use site (SU2-A6)
- Correct redirect-layer comments and guard wildcard prefix boundary (SU2-A7)
- Cover docs-host hardening branches, compile matcher via path-to-regexp (SU2-A8)
2026-06-11 14:00:20 -07:00
Jordan Ritter 426ae3a8e1 fix(showcase/shell): SEO redirect table + middleware matcher hardening (SU-2/8/11/14/15/16/17/18/19/20)
Resolve SEO redirect destinations against the docs host (SU-17); forward
the query string on SEO redirects (SU-16); match bare paths on wildcard
SEO sources (SU-19). Collapse duplicate slashes in docs-host redirect
destinations (SU-13). Regression test for /shared//evil.com open redirect
(SU-18). Emit 308 for docs-host redirects to match next.config parity
(SU-2). Add a path boundary to the api matcher exclusion (SU-15). Loud
guard when registry yields zero framework slugs (SU-20). Keep PostHog
capture alive via event.waitUntil (SU-14). Note docs-host redirects are
untracked by design (SU-8). Cover docs-host redirects at the middleware
level (SU-11).

Squash of the SEO-table + matcher-hardening cluster.
2026-06-11 14:00:03 -07:00
Jordan Ritter febd8bc946 feat(showcase/shell): runtime-derived backend URLs and docs-host redirects (SU-13)
Carry backendHostPattern + docsHost in the shell runtime config (no longer
baked from registry.json at Docker build time). Derive demo backend URLs at
runtime from the pattern; issue docs-host 301s from middleware with a runtime
DOCS_HOST so a misconfigured value can no longer 500 every docs route.

Validate NEXT_PUBLIC_LOCAL_BACKENDS and empty overrides; guard the backend
host pattern against silent env misconfigs. Reword the stale demo-page
comment about backend URL derivation. Pin the registry slug set and SSR
placeholder URL composition; fix env/spy/global leaks in runtime-config
test cleanup.

Squash of the initial runtime-URL refactor cluster:
- feat(showcase): carry backendHostPattern + docsHost in shell runtime config
- fix(showcase): derive demo backend URLs at runtime instead of baked registry values
- fix(showcase): issue docs-host 301s from middleware with runtime DOCS_HOST
- fix(showcase): never let a misconfigured DOCS_HOST 500 every docs route
- fix(showcase): guard backend host pattern against silent env misconfigs
- fix(showcase): validate NEXT_PUBLIC_LOCAL_BACKENDS values and empty overrides
- docs(showcase): reword stale demo-page comment about backend URL derivation
- test(showcase): fix env/spy/global leaks in runtime-config test cleanup
- test(showcase): pin registry slug set and SSR placeholder URL composition
2026-06-11 13:59:46 -07:00
Jordan Ritter 9871d06671 refactor(showcase): rename getRuntimeConfigEdge to getRuntimeConfigForMiddleware
Clarify the wrapper's role (it forces noStore:false because unstable_noStore is
unavailable in middleware/Edge). Pure rename across shell, shell-docs, and
shell-dashboard: definitions, middleware call sites, and tests. No behavior
change.
2026-05-30 10:22:35 -07:00
Jordan Ritter 8714ab569b chore(showcase): apply oxfmt formatting across showcase scripts and shells
oxfmt --write normalized formatting on showcase scripts, the four shells, and the
new oxlint rule; required for the repo-root oxfmt --check CI gate.
2026-05-29 11:45:16 -07:00
Jordan Ritter 09b9f8910b chore(showcase): pre-push cleanup -- comment rot, log levels, env coalesce, test hardening
Non-functional cleanup pass on the showcase deploy-pipeline integration
branch. All changes are scoped to comment rot, log severity for already-
demoted runtime-config fields, length-aware env-name coalescing (a
deliberately-empty primary no longer masks a populated alternate), and
test-quality tightening. No production behavior change beyond the
specific items below.

Changes by area:

- shell/shell-dashboard/shell-docs runtime-config.ts: factor the
  `process.env[primary] ?? process.env[alt]` chain into a shared
  length-aware `readEnvPair` helper. The prior `??` form treated
  `PRIMARY=""` as set, masking a populated alternate; the helper now
  treats empty-string as unset and falls through to the alternate.
- shell-docs runtime-config.ts: demote the two recoverable URL fields
  (`intelligenceSignupUrl`, `posthogHost`) from console.info to
  console.warn. The `FATAL-CONFIG:` Sentry-alert prefix is preserved
  only on the true sentinels; the demoted fields now clear prod log-
  aggregation thresholds without raising ops alerts.
- All three shells' runtime-config.ts: prefix log lines with the shell
  name (e.g. `[shell-docs runtime-config]`) so the shared log stream
  identifies which shell emitted the line.
- shell-docs runtime-config-serialize.ts: rewrite the U+2028 / U+2029
  RegExp arguments using six-character ASCII backslash-u escape
  sequences (was: literal codepoints in the string arg). The literal
  codepoints are line terminators that a formatter or editor could
  silently strip, breaking the security-critical XSS escape. The
  ASCII form is robust to any such pass.
- shell-docs use-google-analytics.test.ts: de-tautologize the hook-
  order test. It now asserts `usePathname(` and `useEffect(` both
  exist in the source, so deleting all hooks would fail the test
  rather than trivially satisfying the early-return path.
- shell-dashboard baseline-types.test.ts: update the partner-count
  expectation from 25 to 26 -- the 26th entry (Cloudflare) is a
  legitimate integration that landed independently; the test was
  stale and had nothing to do with this branch.
- scripts/resolve-verify-matrix.ts: drop the `FIX 7 --` plan-
  internal prefix from a comment; keep the explanation.
- shell-docs/.env.example: correct the `NEXT_PUBLIC_SHELL_URL`
  fallback claim (sentinel, not canonical prod host) and document
  the remaining 7 consumed env vars with their FATAL/warn/silent
  semantics so the example matches runtime-config.ts.

Skipped:
- C-SENTINEL-DEDUP (`http://ops.invalid` shared constant across
  shell-dashboard's next.config.ts and runtime-config.ts): both
  files are at different module levels (root vs src/lib) and the
  string appears once in each; extracting to a shared module would
  widen the diff into a refactor for marginal benefit. Skipped per
  the spec's "if it widens diff awkwardly, skip" guidance.
- C-SSRTEST: already exhaustively covered. Each of the three shells
  has an SSR placeholder test that exercises every URL field via
  `new URL()` parseability and (for shell-docs) the analytics-key
  empty-string semantics. Treated as a no-op.

Validation: shell + shell-dashboard + shell-docs runtime-config /
serialize / GA tests green; bin/showcase Ruby suite green (87 runs);
showcase/scripts resolve-verify-matrix + aggregate-build-results +
lint-rule-no-public-env green (79 runs).
2026-05-29 11:45:15 -07:00
Jordan Ritter 28f33ecc8a fix(showcase): stop SSR 500 + hook-order regressions in shell runtime-config; tolerate env-name variants
Six fixes addressing CR findings on the Option-B runtime URL-injection migration:

1. SSR_PLACEHOLDER must be parseable URL sentinels — `new URL("")` throws on
   SSR causing 500s for any consumer that constructs URLs from runtime-config
   fields. Use `.invalid`-TLD sentinels (RFC 2606) for URL fields; analytics
   keys stay empty string. Add `suppressHydrationWarning` on consumers that
   render the placeholder server-side and the real value post-hydration
   (integration-grid, page-actions popover).

2. Hook-order: move `usePathname()`/`useEffect` ABOVE the early-return in
   use-google-analytics. Gate the effect bodies on `GA_ID` instead so React
   sees a stable hook order across renders.

3. `readUrl`/`readKey` accept either bare or `NEXT_PUBLIC_*`-prefixed env
   names via a fallback chain — covers both server-only and inlined-public
   variable conventions without forcing a rename across deploy targets.

4. Extract `serializeRuntimeConfig` to `lib/runtime-config-serialize.ts` so
   the OWASP-escape behavior (XSS via </script>, U+2028/U+2029 line-terminator
   injection) can be unit-tested without importing the layout into vitest.

5. Reclassify `intelligenceSignupUrl`/`posthogHost` from FATAL-CONFIG to
   info-level in shell-docs — these are optional integrations, not hard
   wiring failures, so absence should not poison the error stream.

6. Comment-rot cleanup: drop "Option B", B12, "the bug we are fixing", fix
   "four substrings"→"three substrings" miscounts, and refresh shell-docs
   .env.example to describe the runtime-injection contract instead of a
   stale next.config throw claim.

V1: shell + shell-docs `next build` succeeds (no Edge-runtime crash on
`unstable_noStore`).
V2: `OPS_BASE_URL=` shell-dashboard `next build` no longer throws —
`next.config.ts` is now a phase-aware function that emits a sentinel
destination at build time and throws only at start (PHASE_PRODUCTION_BUILD
from next/constants).

Tests: shell-docs 72/72, shell 12/12, shell-dashboard runtime-config 16/16
(pre-existing baseline-partner-count failure unchanged).
2026-05-29 11:45:15 -07:00
Jordan Ritter 6d9d48ddd0 fix(showcase): SSR-safe runtime-config client for shell-docs/shell/shell-dojo (sentinel, not throw)
getRuntimeConfig() in each shell's runtime-config.client.ts threw when
typeof window === 'undefined'. But Next.js App Router executes 'use
client' component bodies on the SERVER during initial SSR, so any client
component that called getRuntimeConfig() in its render body 500'd the
page. shell-dashboard already had the fix.

Mirror shell-dashboard's pattern: return a typed SSR_PLACEHOLDER (empty
strings for URL/key fields; {} for shell-dojo whose RuntimeConfig is
empty) when window is undefined. Keep the loud throw when window IS
present but window.__SHOWCASE_CONFIG__ is missing — that's a genuine
wiring bug and should not be masked.

Updated shell-docs and shell client tests: replace 'throws on server'
case with 'returns SSR sentinel placeholder' assertion matching each
shell's RuntimeConfig shape. shell-dojo has no client test so verified
via tsc only.
2026-05-29 11:45:09 -07:00
Jordan Ritter 839ec9c573 refactor(showcase): migrate shell middleware to runtime-config
Replaces the module-load read of NEXT_PUBLIC_POSTHOG_HOST in
showcase/shell/src/middleware.ts (which Next inlines into the Edge
bundle at build time and freezes per artifact) with a per-request
read via getRuntimeConfigEdge().posthogHost. The Edge wrapper skips
unstable_noStore() — next/cache is not available in the Edge
runtime, and middleware always runs per-request so there is no
static cache to opt out of.

Refs plan-B §B9.6.
2026-05-29 11:45:07 -07:00
Jordan Ritter ef3c7d7b7b refactor(showcase): inject __SHOWCASE_CONFIG__ in shell root layout
Adds a <head> element (shell previously had only <html> → <body>) and
emits an inline <script> as its first child that writes
window.__SHOWCASE_CONFIG__ from the server-side runtime config before
any client component mounts. The injection JSON is OWASP-escaped:
< → < (guards against </script> breakout from a hostile env
value), and U+2028 / U+2029 are escaped to 
 / 
 (line
separators are legal inside JSON strings but a syntax error inside a
JS string literal in pre-ES2019 engines / when parsed as
text/javascript).

The commit-sha overlay continues to read process.env.NEXT_PUBLIC_COMMIT_SHA
directly — COMMIT_SHA is build-stamped intentionally (identifies the
artifact, not the env).

Refs plan-B §B6.
2026-05-29 11:45:07 -07:00
Jordan Ritter 83af6b8530 feat(showcase): add shell runtime-config server+client
Introduces showcase/shell/src/lib/runtime-config.ts (server-only —
imports next/cache and is read at request time by the root layout)
plus runtime-config.client.ts (reads window.__SHOWCASE_CONFIG__
injected by the layout). Shell's RuntimeConfig contains baseUrl and
posthogHost. getRuntimeConfigEdge() provides the Edge-runtime variant
for middleware (skips unstable_noStore).

Adds vitest config + dev deps to package.json and red-green tests for
both modules. Tests verify env-vs-fallback precedence, trailing-slash
stripping, no-module-load-freeze (live process.env reads per call),
and the Edge wrapper's noStore-skip behavior.

Refs plan-B §B7.
2026-05-29 11:45:07 -07:00
Tyler Slaton a5050dbe26 fix(showcase): retarget R15/R17 in legacy shell + harness copies
The shell-docs port (e2bef7a0b) updated R15/R17 sources to /integrations/built-in-agent
in showcase/shell-docs/src/lib/seo-redirects.ts and refreshed the snapshot fixture, but
left the legacy shell copy (showcase/shell/src/lib/seo-redirects.ts) and the harness
intentional-copy (showcase/harness/src/probes/drivers/seo-redirects.ts) on the old
/builtin-agent value. The redirect-decommission test imports from the legacy shell
file, so the snapshot diverged: fixture says /integrations/built-in-agent but source
generates /builtin-agent. Mirror the retargeting into both copies so all three files
(shell-docs source, shell legacy source, harness synced copy) agree with the fixture
and Validate Showcase passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:41:18 -07:00
github-actions[bot] a2bfa49b9a style: auto-fix formatting 2026-05-07 16:53:44 +00:00
Sam Julien f5a611f20f feat(shell-docs): port redirect middleware + retarget destinations to shell-docs slugs
Part 1 — Retarget seo-redirects.ts destinations:

- Drop the legacy /docs/integrations/ prefix everywhere; shell-docs
  serves canonical framework docs at /<fw-slug>/<...> from the host
  root.
- Apply registry-slug renames in destinations:
    langgraph                  → langgraph-python
    adk                        → google-adk
    aws-strands                → strands
    microsoft-agent-framework  → ms-agent-dotnet
    crewai-flows               → crewai-crews
    unselected                 → built-in-agent (BIA canonical re-flip)
- Add slug-rename catch-alls for the bare /<old-slug>/* form so legacy
  upstream URLs (e.g. /langgraph/quickstart) 301 to the new slug.
- Add /docs/integrations/* and /docs/* catch-alls so any URL still
  carrying the legacy SHELL routing prefix lands at the shell-docs
  equivalent.
- Add /migration-guides/* → /migrate/* (4 URLs).
- Add folder-index redirects for shell-docs folders without an
  index.mdx (/troubleshooting, /migrate, /premium, /concepts,
  /reference) so bare folder URLs land on a representative inner page.

Part 2 — Port the redirect middleware to shell-docs:

- Copy the retargeted seo-redirects.ts to shell-docs/src/lib/.
- Merge the SHELL redirect-middleware logic into shell-docs's existing
  pageview-tracking middleware: redirects fire first (with seo_redirect
  PostHog event), and non-redirected requests still get the
  docs_pageview capture and distinct_id cookie.
- Preserve the framework-scoped short-circuit so canonical
  /<fw-slug>/<...> URLs are never hijacked by legacy patterns.
- Leave the SHELL versions in place — the SHELL still serves
  docs.showcase.copilotkit.ai until DNS flips.

Verified shell-docs and SHELL builds clean. Spot-checked redirects on a
local shell-docs server: /docs/integrations/langgraph/quickstart →
/langgraph-python/quickstart, /langgraph/quickstart →
/langgraph-python/quickstart, /migration-guides/v2 → /migrate/v2,
/troubleshooting → /troubleshooting/common-issues, /coagents →
/langgraph-python, /aws-strands/quickstart → /strands/quickstart.
2026-05-07 09:52:02 -07:00
Sam Julien b355a9aec0 feat(shell-docs): port docs telemetry stack
Brings PostHog, GA4, HubSpot, Reo.dev, Scarf, and RB2B into shell-docs
with parity to docs/. Adds the client-side PostHog provider with
session-stitched bootstrap and pageview capture, the AnalyticsClient
wrapper that mounts RB2B + GA4 hooks behind a single client boundary,
the Scarf pixel for OSS attribution, and the HubSpot and Reo.dev
scripts.

Renames POSTHOG_PROJECT_KEY to POSTHOG_KEY across shell and shell-docs
middlewares so the env names match the upstream pattern, and env-drives
POSTHOG_HOST with eu.i.posthog.com as the fallback.
2026-05-06 15:32:31 -07:00
Alem Tuzlak 5a9b5bdf7e fix(showcase): allow microphone in demo iframe so voice demos work
The shell embeds each demo in a cross-origin iframe whose `allow`
attribute only granted clipboard access. Browsers block
`getUserMedia({ audio: true })` at the Permissions Policy layer in
cross-origin frames unless the parent grants `microphone` via `allow`,
so every voice demo across every integration threw "Microphone
permission denied" before any user prompt was shown.

Add `microphone` to the iframe `allow` in all three places that embed
demo previews — the per-demo viewer, the standalone preview route, and
the demo drawer — so voice demos work uniformly across all 18
integrations. No other demo type uses getUserMedia / getDisplayMedia
/ geolocation, so no other Permissions Policy features are needed.
2026-05-01 10:45:45 +02:00
Jordan Ritter 1cd151e5b8 feat(showcase): add favicon and og:image
Heater shield with CopilotKit kite logo in magenta on dark
background, matching the sub-property icon style across
copilotkit.dev properties. Wires up Next.js metadata for
title, description, icons, and openGraph.
2026-04-29 20:03:33 -07:00
Alem Tuzlak 6f9f3f220e Merge remote-tracking branch 'origin/main' into fix/showcase-shell-cli-start-not-live-demo
# Conflicts:
#	showcase/shell/src/data/registry.json
2026-04-24 13:16:45 +02:00
Alem Tuzlak d936bc726d fix(showcase-shell): guard demo.route in viewer + preview, share Demo type
Review feedback from #4196:

- `[slug]/[demo]/page.tsx` constructed `${backend_url}${demo.route}`
  without a null check, so command-only demos (which have no `route`)
  rendered an iframe pointing at `${backend_url}undefined`. Now builds
  the src only when `demo.route` exists and renders a 'no live preview'
  panel otherwise, mirroring the Get Started section on the profile
  page. Also replaces the `any`-typed state with proper `Demo` and
  `Integration` types imported from `@/lib/registry`.
- `[slug]/[demo]/preview/page.tsx` had the same bug — already typed
  but TypeScript doesn't catch template-literal coercion of undefined.
  Now bails with a command-focused message before concatenating.
- `profile-client.tsx` no longer duplicates `Demo`/`Integration`
  interfaces — deleted the local copies and imports from
  `@/lib/registry`. copyDemoCommand's catch now logs the failure so a
  double-failure (no clipboard API + blocked prompt) is diagnosable.
  Comment above the live-demos section updated from 'Demos' to
  'Live Demos' to match the rendered heading.
2026-04-24 13:06:45 +02:00
Jordan Ritter e772879b73 fix(showcase): gitignore generated data JSON and untrack committed blobs
Add */src/data/*.json patterns to showcase/.gitignore for all 4 shell
apps. Remove 11 tracked JSON blobs (~28K lines of generated content)
that were causing constant git noise from embedded timestamps and
leaking into PRs on every build/dev run.

Every build path (Docker, CI, npm run build, npm run dev) regenerates
these files — they never needed to be committed.
2026-04-23 21:13:12 -07:00
Jordan Ritter 58f95a08ae fix(showcase): strip generated_at timestamps from generators and consumers
Every generator embedded `generated_at: new Date().toISOString()` in its
output, causing constant git noise on every build/dev run even when
actual content was unchanged. Remove the field from all 4 generator
scripts, all consumer interfaces (Registry, BundledContent,
BundledStarters, DocsStatusBundle), inline type casts, and test
assertions.

Also: add shell-dashboard as a generate-registry output directory (it
was cross-importing from shell); move probe-docs output to
shell-dashboard/src/data/ (sole consumer); update test beforeAll to
generate files instead of restoring from git HEAD (prep for gitignore).
2026-04-23 21:12:32 -07:00
devops-bot[bot] 0ce10b6c3d Update preview URLs in registry 2026-04-23 20:27:40 +00:00
Alem Tuzlak 6dff6200e8 feat(showcase): wire open-gen-ui demos, update manifest and constraints
Declare open-gen-ui and open-gen-ui-advanced in langgraph-python
manifest (code existed, was never registered). Add both to
constrained-explicit allowlist, fill shell_docs_path for 5 demos,
add hitl-in-app override, drop stale chat-customization-css fallback.

Regenerate registry.json, demo-content.json, constraints.json,
and docs-status.json across shell / shell-dojo / shell-docs.
Bump feature/demo count assertion 30→32 in generate-registry test.
Extend check-binaries.sh whitelist for sister-shell demo-content.
2026-04-23 12:45:36 -07:00
devops-bot[bot] 667ecac916 Update preview URLs in registry 2026-04-23 19:25:31 +00:00
github-actions[bot] 3b887da707 style: auto-fix formatting 2026-04-23 18:59:34 +00:00
devops-bot[bot] da78e0f874 Update preview URLs in registry 2026-04-23 18:33:23 +00:00
github-actions[bot] f35ede00c6 style: auto-fix formatting 2026-04-23 17:33:01 +00:00
devops-bot[bot] 3683106851 Update preview URLs in registry 2026-04-23 16:51:11 +00:00
github-actions[bot] e94aa1d4e1 style: auto-fix formatting 2026-04-23 16:16:22 +00:00
Jordan Ritter 9bce821779 feat(shell-dashboard): Phase 3 dashboard honesty pass
Phase 3.0: Pre-flight verified — 34 e2e_smoke rows in PB (producer
gap from PR #4200 resolved).

Phase 3.1: Rename dashboard e2e subscription to e2e_smoke to match
ops producer key. Update formatLabel/formatTooltip dim unions.

Phase 3.2: Add per-integration L1-L4 LevelStrip with Up/Wired/Chats/
Tools badges. New subscriptions for agent, chat, tools, e2e_smoke.
Widen aggregateConnection to variadic. Tools n/a gate uses
integration.demos.some(d => d.id === "tool-rendering").

Phase 3.3: Retire HealthDot from per-feature cells (L1 Up badge in
strip replaces it). Drop smokeRow from per-cell rollup (Decision #7).
Rollup now uses [healthRow, e2eRow] only. First-ever green rollups
enabled (smokeRow was always null in production).

Phase 3.4: Remove QA column — drop LiveBadge QA, CellState.qa,
subscription, legend entry. No producer ever existed.

Phase 3.5: Docs four-glyph mapping: ok->checkmark, missing->middle
dot, notfound->cross, error->exclamation. Each DocState has a
distinct glyph and tone.

Phase 3.6: Legend rewrite — drop QA/Hosted, add L1-L4 strip docs,
expand docs row for four glyphs, rewrite ? footnote.

Phase 3.7: Add PackagesSection below starters grid. Extends
registry.json with packages array from shared/packages.json. CI
drift test ensures package set matches integration set.
2026-04-23 09:14:05 -07:00
devops-bot[bot] 63aebe2c00 Update preview URLs in registry 2026-04-23 16:00:34 +00:00
github-actions[bot] a8b08ab49d style: auto-fix formatting 2026-04-23 08:34:37 -07:00
Sam Julien 824553b251 chore(showcase): update generated data and quickstart default integration
- Update registry.json, demo-content.json, status.json, constraints.json,
  docs-status.json across shell/shell-docs/shell-dojo
- Add integration="langgraph-python" default to quickstart InlineDemo so
  the base unscoped page shows a demo instead of being empty
2026-04-23 08:34:37 -07:00
github-actions[bot] 630f6743d9 style: auto-fix formatting 2026-04-23 12:11:52 +00:00
Alem Tuzlak 968f2fe378 fix(showcase-shell): separate CLI init command from live demos
The cli-start entry in each integration's demos[] is a copy-paste CLI
command, not a runnable demo, but the profile page rendered it as a
Live Demo tile whose drawer iframe loaded ${backend_url}undefined.

Split demos into liveDemos (runnable) and commandDemos (command-only)
and render commandDemos in a new "Get Started" section above the
Live Demos grid, mirroring how the dashboard already handles them.
2026-04-23 14:08:54 +02:00
devops-bot[bot] 4ae9af088e Update preview URLs in registry 2026-04-23 02:12:08 +00:00
github-actions[bot] f5b66a4088 style: auto-fix formatting 2026-04-22 19:20:30 +00:00
devops-bot[bot] 432345485f Update preview URLs in registry 2026-04-22 18:53:07 +00:00
Jordan Ritter af35569d7d chore(showcase/packages): QA markdown parity + integration tooling
Rename hitl.md → hitl-in-chat.md across all 17 showcase packages,
add shared-state-read / shared-state-write / shared-state-streaming /
gen-ui-agent / subagents QA docs where missing, update demos/hitl
README cross-links. Refresh showcase/shell + shell-dojo registry +
demo-content JSON to match new QA shape. Update integration tooling
(audit, create-integration, bundle-demo-content, generate-registry,
validate-parity, capture-previews, manifest lib) + e2e tests to the
new parity contract.
2026-04-22 11:00:46 -07:00
Alem Tuzlak c92dde419b fix(showcase): complete open-gen-ui scrub + fix smoke-test filter regression (#4029)
## Summary
Prior PR removed the open-gen-ui feature but left several loose ends.
This PR completes the scrub:

1. **Source YAML** — removed `open` profile + `open-gen-ui` entries from
`showcase/shared/constraints.yaml` (was missed before; would have
re-introduced `open-gen-ui` on next generator run)
2. **Schema enum** — dropped `"open"` from `generative_ui` enum in
`showcase/shared/manifest.schema.json`
3. **Test fixture** — `invalid-genui-manifest.yaml` now uses
`[unknown-profile]` instead of `[open]`; tests still pass (validator
rejects unknown profiles)
4. **Manifest descriptions** — all 17
`showcase/packages/*/manifest.yaml` files: "5 GenUI rendering
strategies" → "4" (open-gen-ui was the 5th; now removed)
5. **Derived JSON regen** — `registry.json` regenerated cleanly via
`generate-registry.ts`
6. **Smoke-test filter fix** — `integration-smoke.spec.ts:383` now reads
top-level `i.deployed` instead of stale `i.starter?.deployed`. The old
filter returned 0 starters post-regen (silent CI skip every 6h); new
filter correctly gates on canonical top-level field.

## Context
- `showcase/shell/src/data/demo-content.json` is also regenerated but
NOT committed because it exceeds the lefthook 1MB binary-size cap
(pre-existing repo condition, separate from this PR).
- 3 starters (mastra, crewai-crews, claude-sdk-typescript) that had
manually-patched `starter.deployed: false` are now covered by smoke —
verified all 3 starter URLs respond HTTP 200 live.

## Test plan
- [ ] CI green
- [ ] Post-merge `starter-smoke` workflow picks up all 17 starters (not
zero, as was the silent broken state)
- [ ] No `open-gen-ui` references remain anywhere in showcase/
2026-04-22 14:34:14 +02:00
github-actions[bot] e713ad2a07 style: auto-fix formatting 2026-04-22 11:20:02 +00:00
Alem Tuzlak 06d24fd8ba Merge remote-tracking branch 'origin/main' into fix/scrub-open-gen-ui
The scrub and #4084 touched the same surface: #4084 re-added an `open:`
generative_ui profile listing `open-gen-ui`/`open-gen-ui-advanced`, and
re-added both features to `constrained-explicit.allowed`. Extending the
branch's scrub to both re-additions keeps the semantic consistent with
the schema (which already dropped `open` from the approaches enum).

- `showcase/shared/constraints.yaml`: drop `open-gen-ui` +
  `open-gen-ui-advanced` from `constrained-explicit.allowed`; drop main's
  re-added `open:` profile entirely.
- `showcase/packages/langgraph-python/manifest.yaml`: drop the now-orphan
  `open-gen-ui` + `open-gen-ui-advanced` feature and demo entries
  (validator confirmed they had no allowed approach left).
- Regenerated `showcase/shell/src/data/registry.json` + sibling
  `shell-docs`/`shell-dojo` registries and `constraints.json` via
  `pnpm --dir showcase/scripts generate-registry`. All 17 integrations
  validate.

`feature-registry.json` intentionally still defines both features — the
original scrub commits (2b996c54d, 27f886e59) left it untouched, so the
demo source files on disk also stay. Follow-up deletion if desired is
out of scope for this merge.
2026-04-22 13:17:34 +02:00
Alem Tuzlak 7c00903c6a Merge remote-tracking branch 'origin/main' into jpr5/ci-workflow-optimization
# Conflicts:
#	.github/workflows/showcase_capture-previews.yml
2026-04-22 13:03:04 +02:00
github-actions[bot] b241d75652 style: auto-fix formatting 2026-04-22 00:37:17 +00:00
Jordan Ritter e2a6cc2bfe Regenerate shell-dojo registry at build and expand CI trigger paths
The dojo app was missing items under the langgraph column because
shell-dojo shipped a stale committed registry.json. The generator
only wrote to shell/, the dojo Dockerfile didn't run the generator
at build, and the CI path filter didn't rebuild the dojo when
manifest files changed.

Fix: emit from generate-registry.ts to shell, shell-dojo, and
shell-docs; add the generator step to shell-dojo's Dockerfile;
expand the deploy workflow's path filter to include packages/**
and shared/**; and refresh the committed registry/demo-content
JSON so files on disk match what the generator produces today.
2026-04-21 13:10:52 -07:00
Jordan Ritter c298fe2ae2 fix(showcase/shell-docs): move 4085-added unselected/prebuilt-components content into shell-docs
These files were added in #4085 but landed in showcase/shell/src/content/docs/
after the MDX-docs extraction had already moved the rest of content/docs into
shell-docs. Follow The Rule (MDX docs content belongs in shell-docs) and
relocate them so they render correctly on docs.showcase.copilotkit.ai.
2026-04-20 14:00:57 -07:00