diff --git a/AUDIO-PLAYBACK-FIX.md b/AUDIO-PLAYBACK-FIX.md new file mode 100644 index 00000000..d13f3d7f --- /dev/null +++ b/AUDIO-PLAYBACK-FIX.md @@ -0,0 +1,51 @@ +# WRNexusJS CAPTCHA audio playback fix + +This patch fixes audio CAPTCHA playback in production and bundled server builds. + +## Root cause + +`AssetAudioRenderer` originally located WAV files only from `import.meta.url`. After +WRNexusJS bundles the server into `dist/server.js`, that URL points to the app build +folder instead of `packages/captcha`, so `/api/captcha/audio/...` fails while trying +to read the WAV clips. + +## Changes + +- Resolves audio assets from the installed `@wrnexus/captcha/audio` package entry. +- Supports `WRNEXUS_CAPTCHA_AUDIO_DIR` for custom deployments. +- Searches workspace and `node_modules` layouts as safe fallbacks. +- Keeps the browser `Audio` instance alive while it plays. +- Stops old audio when a new challenge is loaded. +- Returns a clear HTTP 503 and server log if audio rendering fails. +- Adds a real WAV rendering test. + +## Apply + +Extract this ZIP into the WRNexusJS repository root and replace the included files. +Then run: + +```bash +bun run typecheck +bun test packages/captcha +bun run --cwd examples/captcha-showcase check +``` + +Restart the server. If running the production build, rebuild first: + +```bash +bun run --cwd examples/captcha-showcase build +bun examples/captcha-showcase/dist/server.js +``` + +## Verify + +1. Open the browser Network panel. +2. Click **Listen**. +3. The `/api/captcha/audio/?key=...` request must return HTTP 200. +4. Its `content-type` must be `audio/wav`. + +For a nonstandard package layout, set an absolute path before starting the server: + +```powershell +$env:WRNEXUS_CAPTCHA_AUDIO_DIR="E:\WireJS\packages\captcha\assets\audio" +``` diff --git a/CAPTCHA-FIX8-README.md b/CAPTCHA-FIX8-README.md new file mode 100644 index 00000000..00172b5e --- /dev/null +++ b/CAPTCHA-FIX8-README.md @@ -0,0 +1,40 @@ +# WRNexusJS CAPTCHA Fixed 8 + +Extract this ZIP directly into the WRNexusJS repository root and allow the included files to replace the current CAPTCHA files. + +## Added + +- 18 concrete generated CAPTCHA image styles +- `imageStyle="random"` +- `allowedStyles` and `excludedStyles` +- `randomizeStyle` +- Resolved style metadata and browser event details +- Easy, normal, hard, controlled-pool, and full renderer showcase at `/styles` +- Tailwind Iconify/Lucide showcase dependencies +- Faster CRC32 PNG encoding +- Safe floating-point line rendering for web, darts, distortion, wave, and scribble effects +- Tests for every renderer and style-pool rule + +## Supported styles + +`classic`, `collision`, `snow`, `corrosion`, `spiderweb`, `cross-shadow`, `split`, `split2`, `cut`, `darts`, `distortion`, `stitch`, `striped`, `wave`, `grid-noise`, `scribble`, `pixel`, `broken-lines`, and `random`. + +## After extraction + +```bash +bun install +bun run scripts/generate-ui-component-reference.mjs +bun run typecheck +bun test packages/captcha +bun test services/managed-captcha +bun run --cwd examples/captcha-showcase check +bun run --cwd examples/captcha-showcase dev +``` + +Open: + +```text +http://localhost:3000/styles +``` + +Use a hard browser refresh after restarting the development server. diff --git a/CAPTCHA-FIXED7-INSTRUCTIONS.md b/CAPTCHA-FIXED7-INSTRUCTIONS.md new file mode 100644 index 00000000..37d58bac --- /dev/null +++ b/CAPTCHA-FIXED7-INSTRUCTIONS.md @@ -0,0 +1,51 @@ +# WRNexusJS CAPTCHA Fixed 7 + +Extract this patch directly into the WRNexusJS repository root and allow files to be replaced. + +## Added + +- `size="compact"`, `size="normal"`, and `size="big"` +- Backward-compatible `small`/`sm`, `large`/`lg`, and `compact="true"` aliases +- `showListen="true|false"` for the Listen button +- Existing `showAudio="true|false"` remains the broader audio-alternative switch +- Self-hosted `type="not-robot"` checkbox challenge +- Showcase examples and tests for all new behavior +- Managed API/OpenAPI support for `not-robot` + +## Usage + +```wrn + +``` + +```wrn + +``` + +The not-robot checkbox is server verified. It uses a one-time challenge, minimum completion time, honeypot, expiry, attempt limits, action binding, optional hostname/session/IP binding, and a single-use response token. It is a low-friction mode; high-risk traffic should escalate to a visual challenge or an external provider. + +## Regenerate and test + +```bash +bun run scripts/generate-ui-component-reference.mjs +bun run typecheck +bun test packages/captcha +bun run --cwd examples/captcha-showcase check +bun run --cwd examples/captcha-showcase dev +``` + +Hard-refresh the browser after restarting the development server. diff --git a/MANIFEST.md b/MANIFEST.md new file mode 100644 index 00000000..5515daec --- /dev/null +++ b/MANIFEST.md @@ -0,0 +1,38 @@ +# Bundle manifest + +## Package + +- Engine, challenge generators, optimized PNG renderer, audio renderer +- Memory, SQLite-compatible, and Redis-compatible stores +- Self-hosted, managed, Turnstile, reCAPTCHA, hCaptcha, and custom providers +- HTTP handlers, guards, page gates, adaptive policy, validation integration +- Plugin and DevToolbar audit panel +- Tailwind-only `Captcha.wrn` with compact/normal/big sizing, listen visibility, not-robot mode, 25–75 disturbance control, and generated image renderer props +- English WAV audio assets +- Unit tests for all 18 PNG renderers, style resolution, security behavior, and documentation + +## Example + +- All self-hosted challenge types, including the not-robot checkbox +- Audio and invisible examples +- Shared `@wrnexus/validation` contact schema with client and API validation +- Protected form API using `captchaGuard` +- Working once-per-session protected-page grant and safe return redirect +- Compact, normal, and big component examples +- Listen-visible and listen-hidden examples +- Easy, normal, and hard image-disturbance examples +- Dedicated `/styles` gallery with 18 concrete renderers, random selection, allowed pools, and excluded pools +- External-provider placeholders + +## Managed service + +- Project keys, allowed hostnames, quotas, key rotation +- Public create/solve and secret-authenticated verification routes +- Memory reference store, SQL migration, OpenAPI specification + +## Integration + +- Repeat-safe installer +- TypeScript path aliases +- Current component-discovery compatibility copy +- Generated 18-style preview gallery and renderer guidance diff --git a/README.md b/README.md index f82f6bee..228ab710 100644 --- a/README.md +++ b/README.md @@ -1,1536 +1,39 @@ -# WrNexus +# WRNexusJS CAPTCHA complete bundle -> **WRNexusJS 0.3 architecture:** see [the language specification](docs/WRN-LANGUAGE-SPEC-1.0.md), -> [architecture guide](docs/ARCHITECTURE-0.3.md), [upgrade guide](docs/UPGRADE-0.3.md), and -> [40-point implementation matrix](docs/40-POINT-IMPLEMENTATION-0.3.md). Validate a release with -> the [one-by-one test checklist](docs/TEST-CHECKLIST-0.3.md) and [audit record](docs/AUDIT-0.3.md). -> An **SSR-first** full-stack web framework MVP with **server-rendered, reactive -> components**. Built in TypeScript, **Bun-first**, Node-friendly where possible. +This bundle targets WRNexusJS `main-80` / package version `0.3.6` and contains: -It gives you file-based pages and API routes, middleware, realtime WebSocket -routes, opt-in client hydration, and the custom `.wrn` language/compiler through -one shared syntax and runtime model. +- `packages/captcha`: publishable `@wrnexus/captcha` package +- `packages/captcha/components/Captcha.wrn`: Tailwind-only UI component +- `examples/captcha-showcase`: runnable challenge, disturbance, validated-form, and protected-page showcase +- `services/managed-captcha`: managed API starter with projects, keys, hostname restrictions, quotas, and rotation +- `scripts/install-captcha.mjs`: repeat-safe repository installer +- `integration`: integration notes and generated path changes +- `docs/IMAGE-STYLES.md`: renderer catalog with a generated preview gallery -> πŸ“˜ **[The Complete Guide](docs/GUIDE.md)** β€” one document covering every package, -> the whole `.wrn` language, all attributes/config properties, and a step-by-step -> path from `create` to a full app (pages, APIs, DB, auth, realtime, deploy). - ---- - -## Why SSR-first with reactive components? - -- **Fast, robust default.** Pages render to HTML on the server, so users get - content immediately and pages work even before (or without) JavaScript. -- **Ship JS only where needed.** A page is plain HTML until it mounts a component - with `data-component=""`. Components render on the server too; only their - reactive state and forms run on the browser β€” the rest ships zero JavaScript. -- **Clean separation.** Server rendering (`@wrnexus/ssr`) never touches the DOM or - client runtime; client hydration (`@wrnexus/csr`) never runs on the server. They - meet only at one seam: a single runtime, `/__wrnexus/reactive.js`. - ---- - -## Installation - -Requires [Bun](https://bun.sh) β‰₯ 1.3.0. +## Install into a WRNexusJS checkout ```bash -bun install -bun run dev # runs examples/basic-app at http://localhost:3000 +bun scripts/install-captcha.mjs /path/to/WRNexusJS \ + --with-showcase \ + --with-managed-service \ + --check ``` -## CLI commands +The installer copies the package, places `Captcha.wrn` in `packages/ui/components` for current component discovery, adds TypeScript aliases, optionally installs the example and managed service, and can run validation commands. -```bash -wrnexus dev [app-dir] [--port=3000] # start the dev server (HMR + regenerates typed queries) -wrnexus build [app-dir] # build the production server bundle + assets -wrnexus generate mobile # scaffold a Capacitor iOS/Android shell -wrnexus mobile add @capacitor/camera # install a native plugin + sync projects -wrnexus create # scaffold a new app -wrnexus generate # scaffold a page | component | api | schema (alias: g) -wrnexus eject # copy a Wire UI component into app/components -wrnexus test [app-dir] [--watch] # run the app's tests (bun test, `test` profile) -wrnexus profiles [app-dir] # list config profiles (dev/prod/uat/…) + their env files +Read `packages/captcha/README.md`, `packages/captcha/SECURITY.md`, and `services/managed-captcha/README.md` before production deployment. -# Database -wrnexus db migrate # apply pending migrations -wrnexus db rollback # revert the last migration -wrnexus db status # list applied / pending migrations -wrnexus db new [--from-models] # scaffold a migration (optionally from TS models) -wrnexus db generate # (re)generate typed queries from app/db/queries/*.sql -wrnexus db seed # run app/db/seed.ts (re-runnable dev data) -wrnexus db studio [table] # list tables + row counts, or dump a table's rows -``` - -### Mobile and PWA - -The same `view` HTML renders in browsers and in the Capacitor app. Add device -directives directly to normal elements. Camera directives use the native camera -in Capacitor, phone camera capture in supported mobile browsers, and a file -picker in desktop browsers. The markup and responsive theme remain shared. - -Cross-platform capabilities can also be declared directly in `.wrn` markup: - -```html - - -

Browser help

- - -``` - -Use `wrnexus native list` to see built-in capabilities and -`wrnexus native add camera share` to install the packages required by the configured -Capacitor or Expo mode. Advanced browser code can use `native.run()` and register -custom adapters from `@wrnexus/native`. - -The declarative `data-native-browser` and `data-native-mobile` capability actions run -in browser and Capacitor/WebView pages. Fully native Expo compilation supports -`data-native-only` and `@mobile-*` event selection, but capability calls must currently -use the installed Expo module from native screen code; the compiler reports an -actionable error instead of silently dropping a `data-native-mobile` action. - -```wrn -page Home { - view { -
- Captured photo - - -
- } -} -``` - -Configure native and installable-web behavior in `wrnexus.config.ts`: - -```ts -const config: AppConfig = { - mobile: { - mode: "webview", // "webview" (Capacitor) or "native" (Expo/React Native) - enabled: true, - appId: "com.example.app", - appName: "Example", - serverUrl: "http://192.168.0.10:3000", - // Native mode uses this backend URL instead of rendering server HTML: - apiUrl: "https://api.example.com", - scheme: "example", - layout: "mobile", // optional app/layouts/mobile.wrn - icon: "resources/icon.png", - // Mode-specific advanced settings: - capacitor: { ios: { contentInset: "automatic" } }, - expo: { orientation: "portrait" }, - }, - pwa: { - enabled: true, - id: "/", - name: "Example", - shortName: "Example", - startUrl: "/", - scope: "/", - orientation: "any", - display: "standalone", - themeColor: "#6366f1", - backgroundColor: "#0f172a", - offlineUrl: "/", - cacheUrls: ["/", "/about"], - cacheName: "wrnexus-pwa-v1", // change to invalidate installed caches - }, -}; -``` - -PWA support is on by default: the framework serves `/site.webmanifest`, `/sw.js`, -injects install metadata, precaches configured offline URLs, and registers a -network-first service worker. Set `pwa.serviceWorker: false` to keep only the -manifest, or `pwa: false` to disable PWA support. Generated Capacitor shells include `error.html`, so -an unreachable server shows a retry screen instead of a blank WebView. - -Generate the configured mode with `wrnexus generate mobile`. You can override it -once with `--mode=webview` or `--mode=native`. WebView mode shares `.wrn` pages -through Capacitor. Native mode creates an Expo/React Native project with native -controls, file-based screens, and a typed backend helper; it shares WrNexus API, -upload, authentication, and realtime endpoints, but not HTML views. - -In native mode, `wrnexus mobile compile` converts `app/pages/**/*.wrn` into -matching Expo Router routes under `mobile/app/`. Portable tags are mapped to -React Native primitives (`div/main` β†’ `View`, text tags β†’ `Text`, `button` β†’ -`Pressable`, `input` β†’ `TextInput`, and `img` β†’ `Image`). State, interpolation, -events, `{#if}`, `{#each}`, class styles, and links are compiled to native JSX. -Unsupported DOM elements, inline CSS strings, SSR/data blocks, and browser APIs -produce compile errors instead of silently falling back to a WebView. - -From this repo the same commands are wired as root scripts: - -```bash -bun run dev # = wrnexus dev examples/basic-app -bun run build # = wrnexus build examples/basic-app -bun run create # = wrnexus create -``` - -Quality checks are wired at the repo root: - -```bash -bun run typecheck # TypeScript check -bun run lint # ESLint -bun run lint:fix # ESLint autofix -bun run format # Prettier write -bun run format:check # Prettier check -bun run check # typecheck + lint + format:check -``` - -Apps created with `wrnexus create ` include the same ESLint/Prettier -baseline for app code. - ---- - -## Project structure - -``` -myframework/ - packages/ - core/ # Context, Middleware types, security + error helpers - cli/ # `wrnexus` command (dev / build / create) - dev-server/ # Bun.serve HTTP + WebSocket pipeline - router/ # file-based router (scan + safe match) - ssr/ # server-side document rendering - csr/ # browser reactive runtime (hydrates components) - styles/ # global stylesheet pipeline + app config (CSS frameworks) - compiler/ # `.wrn` language compiler (lexer/parser/codegen) - reactive/ # tiny signal() implementation - examples/ - basic-app/ # reference app exercising every feature - app/ - pages/ # file-based pages -> /, /about - api/ # file-based API routes -> /api/* - middleware/ # global middleware (alphabetical order) - realtime/ # WebSocket routes -> /realtime/* - components/ # reactive components (.wrn, data-component="name") - styles/ # global CSS (global.css -> every page) - public/ # static assets -> /robots.txt, /images/logo.svg - wrnexus.config.ts # optional: SEO, head injection, CSS, security - package.json - tsconfig.json - README.md -``` - -The app folder is convention-based β€” drop a file in the right directory and it -becomes a route. Routes are resolved against a table scanned at startup; request -input is never turned into a file path. - ---- - -## Pages - -`app/pages/index.tsx` β†’ `/` - -```tsx -export const meta = { - title: "Home", - description: "Welcome to WrNexus", -}; - -export default function Home() { - return `

Hello from WrNexus

-
`; -} -``` - -`app/pages/about.tsx` β†’ `/about`. Dynamic segments use brackets: -`app/pages/users/[id].tsx` β†’ `/users/:id`, with `ctx.params.id` available. - -## SSR - -The server renders each page to a full HTML document. Page metadata is escaped -and placed in the ``; the body goes inside `#app`: - -```html - - - - - - Home - - - -
-

Hello from WrNexus

-
- -
-
- - - -``` - -The `
` mount was replaced by the component's -server-rendered HTML, and the reactive runtime is injected only because the page -now contains a `data-scope` (see "Per-page code-splitting" below). Everything in -a page module is **server-only** β€” it is never bundled to the browser. Errors -are readable in development and generic (no file paths) in production. - -## Components (server-rendered, hydrated on the browser) - -Components are `.wrn` files under `app/components`. They render on the **server** -(with their props applied) and are hydrated on the browser by the single generic -reactive runtime β€” they ship no JS of their own. Only forms and reactive state -run in the browser. - -`app/components/counter.wrn`: - -``` -component Counter { - props { - start = 0 // default's type drives coercion (number) - label = "Count" // (string) - } - state count = start - view { - - } -} -``` - -Mount it in any page and pass props as attributes β€” pass as many as you like: - -``` -
-``` - -Each attribute becomes a prop, coerced to the type of its declared default (so -`start="5"` arrives as the number `5`). Prop-driven text and attributes are -**baked server-side** (a static component ships zero JS); text that references -`state` stays reactive. Components (and layouts) can take children via `` β€” -including **named slots**: put `` in the component and fill it -from the mount with `
…
` (anything else fills the -default ``). Component names are validated before rendering. - -## Wire UI, theming & layouts - -**Wire UI** (`@wrnexus/ui`) ships common components β€” `button`, `input`, `select`, -`checkbox`, `radio`, `switch`, `textarea`, `badge`, `tag`, `alert`, `card`, -`avatar`, `spinner`, `skeleton`, `progress`, `tooltip`, `table`, `disclosure`, -`theme-toggle` β€” plus layout primitives `container`, `stack`, `hstack`, `grid`, -`divider`, `spacer`. They are auto-discovered, so you mount them straight away: - -``` -
-
-
-
-``` - -Override styles four ways, least β†’ most control: change a **theme token**, -redefine a **`.wire-*` class** in your CSS, pass a **`class` prop** (appended to -the root), or **`wrnexus eject `** to copy a component into `app/components` -and own it (an app component shadows the library one of the same name). - -**Theming.** Design tokens (`--wire-*`) come from `wrnexus.config.ts` `theme` (deep --merged over built-in light/dark), served at `/__wrnexus/theme.css`. The server -sets `` from the `wire-theme` cookie (no flash); a `theme-toggle` -component (or any `[data-wire-theme-toggle]` element) switches and persists it. -Choose a complete semantic palette with `theme: { palette: "violet" }`. Available -palettes are `blue`, `indigo`, `violet`, `emerald`, `cyan`, `rose`, `amber`, and -`slate`; a custom palette must provide every primary, secondary, info, success, -warning, danger, hover, and contrast color. - -**Page layouts.** Add named layouts under `app/layouts/` β€” e.g. `public.wrn`, -`dashboard.wrn`, `auth.wrn` β€” each a `component` with a `` where the -page body goes. A page picks one by name: - -``` -page Dashboard { - layout = "dashboard" - view {

Overview

... } -} -``` - -Pages with no `layout` fall back to a `default` layout if one exists; `layout = "none"` -opts out. Layouts can mount components (nav, theme-toggle) like any page. - -**Document layout.** A conventional `app/layouts/document.wrn` is applied outside -the selected page layout and may own ``, ``, ``, and `#app`. -The framework passes `cookies`, `theme`, `language`, `url`, and `pathname` as -SSR props, then safely merges page SEO, global head entries, styles, and scripts: - -```wrn -layout Document { - props { cookies = {} theme = "light" language = "en" } - view { - - -
- - } -} -``` - -Cookie-backed document attributes are present in the first server response, so -CSS can apply before paint instead of correcting the page after hydration. - -## API routes - -`app/api/hello.ts` β†’ `/api/hello`: - -```ts -export const GET = async () => Response.json({ message: "Hello API" }); -``` - -Method-specific handlers live in one file; unsupported methods return **405** -with an `Allow` header: - -```ts -export const POST = async (ctx) => { - const body = await ctx.req.json(); - return Response.json({ received: body }); -}; -``` - -## Validation (one schema, form + API) - -Define a schema once in `app/schemas/.ts` with the fluent builder: - -```ts -import { v } from "@wrnexus/validation"; -export default v.object({ - email: v.string().email(), - password: v.string().min(8, "Password must be at least 8 characters"), -}); -``` - -Use it on the **server** in an API route β€” bad input is rejected even if the -client is bypassed: - -```ts -import { parseBody } from "@wrnexus/validation"; -import login from "../schemas/login.ts"; -export const POST = async (ctx) => { - const r = await parseBody(login, ctx.req); - if (!r.ok) return r.response; // 400 { ok:false, errors } - return Response.json({ ok: true }); -}; -``` - -And on the **client** by naming it on a form β€” the framework injects the schema -descriptor + a tiny, eval-free validator that checks on submit/blur and writes -messages into `[data-error]` spans (no per-form JS, CSP-safe): - -``` -
- - - -
-``` - -Valid forms submit via `fetch` (JSON) and stay on the page: on success they -redirect (`data-redirect`) or reveal a `[data-success]` message; server-returned -field errors map back to the `[data-error]` spans. - -## i18n (pages + API) - -Put translations in `app/locales/.json` (nested keys, `{param}` placeholders): - -```json -// app/locales/es.json -{ "home": { "title": "Β‘Hola desde WrNexus!" }, "api": { "greeting": "Hola" } } -``` - -Translate in **views** with the `{t:key}` sugar (and `t:="key"` for -attributes), and in **API/handlers** with `ctx.t`: - -``` -

{t:home.title}

- -``` - -```ts -export const GET = (ctx) => Response.json({ message: ctx.t("api.greeting"), lang: ctx.lang }); -``` - -The active language is resolved per request from the `wire-lang` cookie β†’ the -browser's `Accept-Language` β†’ the config default (`wrnexus.config.ts` `i18n.default`), -and set on `` (no flash). A `[data-wire-lang-set="es"]` element (or -`