diff --git a/app/pages/404.wrn b/app/pages/404.wrn index 7f12379c..e8957f17 100644 --- a/app/pages/404.wrn +++ b/app/pages/404.wrn @@ -7,10 +7,10 @@ page Pagenotfound { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation
- +
} } \ No newline at end of file diff --git a/app/pages/access.wrn b/app/pages/access.wrn index 203279e4..3f9c237a 100644 --- a/app/pages/access.wrn +++ b/app/pages/access.wrn @@ -7,10 +7,10 @@ page Access { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation
-

Request preview access

WRNexusJS 0.8.4 packages are not available from the public npm registry. Installation requires approval and private registry credentials supplied by WorkRoot. Never paste registry tokens into source control, issue reports, or support messages.

Request process

  1. Contact WorkRoot through the public contact path at workroot.in.
  2. Describe the application, team, expected deployment, and Bun environment.
  3. After approval, follow the registry instructions supplied privately.
  4. Use the canonical scaffold command below only after authentication.
bunx @wrnexus/cli@0.8.4 create my-app

Access approval, response time, licensing terms, and support level remain owner-controlled. This site does not collect access requests directly.

- +

Request preview access

WRNexusJS 0.8.5 packages are not available from the public npm registry. Installation requires approval and private registry credentials supplied by WorkRoot. Never paste registry tokens into source control, issue reports, or support messages.

Request process

  1. Contact WorkRoot through the public contact path at workroot.in.
  2. Describe the application, team, expected deployment, and Bun environment.
  3. After approval, follow the registry instructions supplied privately.
  4. Use the canonical scaffold command below only after authentication.
bunx @wrnexus/cli@0.8.5 create my-app

Access approval, response time, licensing terms, and support level remain owner-controlled. This site does not collect access requests directly.

+
} } \ No newline at end of file diff --git a/app/pages/architecture.wrn b/app/pages/architecture.wrn index 6ab0c0ff..b2828fd3 100644 --- a/app/pages/architecture.wrn +++ b/app/pages/architecture.wrn @@ -7,10 +7,10 @@ page Architecture { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation
-
Framework architecture · 0.8.4

Architecture

WRNexusJS is Bun-native and SSR-first. File discovery maps pages and API handlers; middleware enriches or short-circuits a request; the compiler turns .wrn declarations into server render functions and small feature runtimes.

Request and build lifecycle

  1. DiscoverPages, APIs, middleware, components, layouts, schemas, rooms
  2. CompileParse .wrn, validate grammar, generate server code
  3. RequestLimits, security, locale, session, middleware
  4. MatchStatic and dynamic file route
  5. RenderSSR data, escaped interpolation, components, metadata
  6. EnhanceOnly required reactive/directive runtimes

Package boundaries

core owns contexts, middleware, sessions and rooms; router discovers routes; compiler parses .wrn; ssr renders documents; csr supplies browser runtimes; dev-server and cli orchestrate development and builds.

Security and data flow

Validation happens at trust boundaries. Session authentication establishes identity; authorization makes resource decisions. CSP, Trusted Types, CSRF, upload checks, WebSocket origins, request limits, and output escaping are layered controls—not substitutes for application policy.

Realtime and scale

Rooms are process-local unless connected through pub/sub. Redis-backed pub/sub distributes events. Queue durability depends on the selected driver and must be evaluated explicitly.

Workspaces and gateways

The gateway can dispatch multiple applications while preserving route, component, asset, config, and session boundaries. Validate host routing and isolation before production.

Build and deployment

wrnexus build . produces dist/server.js and hashed/static assets. Run the server with Bun, apply migrations before traffic, terminate TLS at a trusted edge, and forward only expected proxy headers.

Mobile

Mobile compatibility bridges SSR-safe Capacitor capabilities; native route generation is experimental and is not general web portability. Test each target platform.

Generated files and limits

app/routes.gen.ts, .wrnexus/, and dist/ are generated. The runtime is Bun-only. Preview packages are private. Historical compatibility and long-term support policy are not yet published.

- +
Framework architecture · 0.8.5

Architecture

WRNexusJS is Bun-native and SSR-first. File discovery maps pages and API handlers; middleware enriches or short-circuits a request; the compiler turns .wrn declarations into server render functions and small feature runtimes.

Request and build lifecycle

  1. DiscoverPages, APIs, middleware, components, layouts, schemas, rooms
  2. CompileParse .wrn, validate grammar, generate server code
  3. RequestLimits, security, locale, session, middleware
  4. MatchStatic and dynamic file route
  5. RenderSSR data, escaped interpolation, components, metadata
  6. EnhanceOnly required reactive/directive runtimes

Package boundaries

core owns contexts, middleware, sessions and rooms; router discovers routes; compiler parses .wrn; ssr renders documents; csr supplies browser runtimes; dev-server and cli orchestrate development and builds.

Security and data flow

Validation happens at trust boundaries. Session authentication establishes identity; authorization makes resource decisions. CSP, Trusted Types, CSRF, upload checks, WebSocket origins, request limits, and output escaping are layered controls—not substitutes for application policy.

Realtime and scale

Rooms are process-local unless connected through pub/sub. Redis-backed pub/sub distributes events. Queue durability depends on the selected driver and must be evaluated explicitly.

Workspaces and gateways

The gateway can dispatch multiple applications while preserving route, component, asset, config, and session boundaries. Validate host routing and isolation before production.

Build and deployment

wrnexus build . produces dist/server.js and hashed/static assets. Run the server with Bun, apply migrations before traffic, terminate TLS at a trusted edge, and forward only expected proxy headers.

Mobile

Mobile compatibility bridges SSR-safe Capacitor capabilities; native route generation is experimental and is not general web portability. Test each target platform.

Generated files and limits

app/routes.gen.ts, .wrnexus/, and dist/ are generated. The runtime is Bun-only. Preview packages are private. Historical compatibility and long-term support policy are not yet published.

+
} } \ No newline at end of file diff --git a/app/pages/benchmarks.wrn b/app/pages/benchmarks.wrn index 87963b98..33da923a 100644 --- a/app/pages/benchmarks.wrn +++ b/app/pages/benchmarks.wrn @@ -7,10 +7,10 @@ page Benchmarks { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation

Benchmarks

No publishable benchmark dataset yet

No comparative speed claims are published. A valid baseline must record scripts, commit, Bun/framework versions, hardware, OS, warmup, samples, workload, raw results, median, percentiles, memory, HTML size, browser JavaScript size, and run date.

The roadmap starts with WRNexusJS-only measurements before any maintained equivalent-workload comparison.

- +
} } \ No newline at end of file diff --git a/app/pages/changelog.wrn b/app/pages/changelog.wrn index 0f6ad1b9..88c094ea 100644 --- a/app/pages/changelog.wrn +++ b/app/pages/changelog.wrn @@ -7,10 +7,10 @@ page Changelog { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation
-

Changelog

0.8.4 2026-07-13

Documentation is aligned to all 46 installed packages. This release adds @wrnexus/helpers, original-request URL helpers, safe login redirects, working wrnexus workspace add, and forward-auth redirect propagation.

Migration notes

Run wrnexus update --latest and keep every @wrnexus/* package on 0.8.4. Existing applications must explicitly add @wrnexus/helpers before importing it; newly scaffolded applications include it automatically.

Versioning and support

The packages use semantic-looking versions, but a formal compatibility and old-release support policy has not been approved. Preview consumers should treat minor releases as potentially requiring migration review.

- +

Changelog

0.8.5 2026-07-13

Documentation is aligned to all 47 installed packages. This release adds @wrnexus/helpers, original-request URL helpers, safe login redirects, working wrnexus workspace add, and forward-auth redirect propagation.

Migration notes

Run wrnexus update --latest and keep every @wrnexus/* package on 0.8.5. Existing applications must explicitly add @wrnexus/helpers before importing it; newly scaffolded applications include it automatically.

Versioning and support

The packages use semantic-looking versions, but a formal compatibility and old-release support policy has not been approved. Preview consumers should treat minor releases as potentially requiring migration review.

+
} } \ No newline at end of file diff --git a/app/pages/examples.wrn b/app/pages/examples.wrn index 1ff2e169..8ae5b047 100644 --- a/app/pages/examples.wrn +++ b/app/pages/examples.wrn @@ -7,10 +7,10 @@ page Examples { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation
-

Examples

Examples are tied to installed 0.8.4 package documentation. The focused snippets in guides are source-verified; standalone runnable projects and CI compilation are tracked as remaining work.

Minimal .wrn page

Documented

Database CRUD

Planned fixture

Authentication and protected route

Planned fixture

Permissions

Planned fixture

Forms and validation

Documented

Realtime dashboard

Planned fixture

File upload

Planned fixture

Background queue

Planned fixture

Redis pub/sub

Planned fixture

Workspace gateway

Planned fixture

Deployment

Planned fixture

Experimental mobile mode

Planned fixture
- +

Examples

Examples are tied to installed 0.8.5 package documentation. The focused snippets in guides are source-verified; standalone runnable projects and CI compilation are tracked as remaining work.

Minimal .wrn page

Documented

Database CRUD

Planned fixture

Authentication and protected route

Planned fixture

Permissions

Planned fixture

Forms and validation

Documented

Realtime dashboard

Planned fixture

File upload

Planned fixture

Background queue

Planned fixture

Redis pub/sub

Planned fixture

Workspace gateway

Planned fixture

Deployment

Planned fixture

Experimental mobile mode

Planned fixture
+
} } \ No newline at end of file diff --git a/app/pages/getting-started.wrn b/app/pages/getting-started.wrn index cef950ad..a19d217d 100644 --- a/app/pages/getting-started.wrn +++ b/app/pages/getting-started.wrn @@ -7,9 +7,9 @@ page Gettingstarted { view {
-
W WRNexusJS
+
W WRNexusJS
Browse documentation
-
Preview guide · v0.8.4

Build a contact inbox

This path creates a server-rendered page, validated API route, middleware, and realtime next step. It requires approved registry access and Bun 1.3.x; this site was verified with Bun 1.3.14.

1. Create the project

bunx @wrnexus/cli@0.8.4 create my-app
+      
Preview guide · v0.8.5

Build a contact inbox

This path creates a server-rendered page, validated API route, middleware, and realtime next step. It requires approved registry access and Bun 1.3.x; this site was verified with Bun 1.3.14.

1. Create the project

bunx @wrnexus/cli@0.8.5 create my-app
 cd my-app
 bun install
 bun run dev

2. Know the structure

app/pages/       # file-based .wrn routes
@@ -39,7 +39,7 @@ export const POST = async (ctx) => {
 }

7. Test and ship

bun run test
 bun run build
 bun dist/server.js

Next: deployment, database, authentication, and workspaces.

- +
} } \ No newline at end of file diff --git a/app/pages/guides/api-routes.wrn b/app/pages/guides/api-routes.wrn index 6badd776..48d7b775 100644 --- a/app/pages/guides/api-routes.wrn +++ b/app/pages/guides/api-routes.wrn @@ -7,10 +7,10 @@ page APIroutes { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

API routes

Export GET, POST, PUT, PATCH, or DELETE from app/api files. Validate request bodies, enforce authentication and authorization, cap request sizes, and return Web Responses.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

API routes

Export GET, POST, PUT, PATCH, or DELETE from app/api files. Validate request bodies, enforce authentication and authorization, cap request sizes, and return Web Responses.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/authentication.wrn b/app/pages/guides/authentication.wrn index 76370725..8fba9f23 100644 --- a/app/pages/guides/authentication.wrn +++ b/app/pages/guides/authentication.wrn @@ -7,10 +7,10 @@ page Authentication { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Authentication

Configure session authentication, log users in through supported auth helpers, and read identity from context. Cookie flags, rotation, expiry, and secret storage remain deployment responsibilities.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Authentication

Configure session authentication, log users in through supported auth helpers, and read identity from context. Cookie flags, rotation, expiry, and secret storage remain deployment responsibilities.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/authorization.wrn b/app/pages/guides/authorization.wrn index 709ab21a..35a57106 100644 --- a/app/pages/guides/authorization.wrn +++ b/app/pages/guides/authorization.wrn @@ -7,10 +7,10 @@ page Authorization { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Authorization

Authentication identifies; authorization decides. Enforce permissions in server routes and policies, including object ownership. UI hiding is never an authorization boundary.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Authorization

Authentication identifies; authorization decides. Enforce permissions in server routes and policies, including object ownership. UI hiding is never an authorization boundary.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/configuration-and-profiles.wrn b/app/pages/guides/configuration-and-profiles.wrn index c2767531..5b10df02 100644 --- a/app/pages/guides/configuration-and-profiles.wrn +++ b/app/pages/guides/configuration-and-profiles.wrn @@ -7,10 +7,10 @@ page Configurationandprofiles { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Configuration and profiles

wrnexus.config.ts owns styles, SEO, security, data, mobile, fonts, and profiles. Keep secrets in validated environment variables and review merged production configuration.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Configuration and profiles

wrnexus.config.ts owns styles, SEO, security, data, mobile, fonts, and profiles. Keep secrets in validated environment variables and review merged production configuration.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/database.wrn b/app/pages/guides/database.wrn index 134851fb..4b9bbb43 100644 --- a/app/pages/guides/database.wrn +++ b/app/pages/guides/database.wrn @@ -7,10 +7,10 @@ page Database { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Database

Configure SQLite or the installed supported driver, keep queries in named SQL blocks, generate typed functions, and apply migrations before traffic. Back up data and test rollback independently.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Database

Configure SQLite or the installed supported driver, keep queries in named SQL blocks, generate typed functions, and apply migrations before traffic. Back up data and test rollback independently.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/deployment.wrn b/app/pages/guides/deployment.wrn index e741ce34..27b0bff4 100644 --- a/app/pages/guides/deployment.wrn +++ b/app/pages/guides/deployment.wrn @@ -7,10 +7,10 @@ page Deployment { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Deployment

Run bun run build, apply migrations, and start dist/server.js with Bun. Configure TLS, proxy trust, environment validation, health checks, graceful restarts, logs, backups, and restrictive security headers.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Deployment

Run bun run build, apply migrations, and start dist/server.js with Bun. Configure TLS, proxy trust, environment validation, health checks, graceful restarts, logs, backups, and restrictive security headers.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/forms-and-validation.wrn b/app/pages/guides/forms-and-validation.wrn index 78b9cc0b..c45d3191 100644 --- a/app/pages/guides/forms-and-validation.wrn +++ b/app/pages/guides/forms-and-validation.wrn @@ -7,10 +7,10 @@ page Formsandvalidation { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Forms and validation

Define a v.object schema, use data-schema on the form, show field errors with data-error, and always call parseBody on the server. refine is server-only.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Forms and validation

Define a v.object schema, use data-schema on the form, show field errors with data-error, and always call parseBody on the server. refine is server-only.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/i18n-and-themes.wrn b/app/pages/guides/i18n-and-themes.wrn index 43e79e28..99be733d 100644 --- a/app/pages/guides/i18n-and-themes.wrn +++ b/app/pages/guides/i18n-and-themes.wrn @@ -7,10 +7,10 @@ page Internationalizationandthemes { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Internationalization and themes

Store locale JSON under app/locales and use translation directives. Themes resolve CSS tokens; ensure contrast, system preference behavior, persistence, and non-color cues.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Internationalization and themes

Store locale JSON under app/locales and use translation directives. Themes resolve CSS tokens; ensure contrast, system preference behavior, persistence, and non-color cues.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/middleware.wrn b/app/pages/guides/middleware.wrn index 61f9c4f6..96e16407 100644 --- a/app/pages/guides/middleware.wrn +++ b/app/pages/guides/middleware.wrn @@ -7,10 +7,10 @@ page Middleware { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Middleware

Middleware receives context and next. Return next() to continue or return a Response to stop. Put request limits and trust-boundary controls before business logic.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Middleware

Middleware receives context and next. Return next() to continue or return a Response to stop. Put request limits and trust-boundary controls before business logic.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/mobile.wrn b/app/pages/guides/mobile.wrn index 9f6249bd..0ba47c9b 100644 --- a/app/pages/guides/mobile.wrn +++ b/app/pages/guides/mobile.wrn @@ -7,10 +7,10 @@ page Mobile { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Mobile

Mobile capabilities are experimental in this preview. Test Capacitor permissions and lifecycle on each platform; do not assume every .wrn or browser API converts to native.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Mobile

Mobile capabilities are experimental in this preview. Test Capacitor permissions and lifecycle on each platform; do not assume every .wrn or browser API converts to native.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/observability.wrn b/app/pages/guides/observability.wrn index 5390c356..0d417897 100644 --- a/app/pages/guides/observability.wrn +++ b/app/pages/guides/observability.wrn @@ -7,10 +7,10 @@ page Observability { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Observability

Use tracking middleware and sinks with redaction, sampling, stable request identifiers, alert ownership, and retention limits. Never capture registry tokens or session secrets.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Observability

Use tracking middleware and sinks with redaction, sampling, stable request identifiers, alert ownership, and retention limits. Never capture registry tokens or session secrets.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/pages-and-components.wrn b/app/pages/guides/pages-and-components.wrn index c0382f67..996d5713 100644 --- a/app/pages/guides/pages-and-components.wrn +++ b/app/pages/guides/pages-and-components.wrn @@ -7,10 +7,10 @@ page Pagesandcomponents { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Pages and components

Pages are routable, components are reusable, and layouts provide shared slots. Mount a component with data-component and keep browser state scoped and minimal.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Pages and components

Pages are routable, components are reusable, and layouts provide shared slots. Mount a component with data-component and keep browser state scoped and minimal.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/project-structure.wrn b/app/pages/guides/project-structure.wrn index 325ead92..b705ebc5 100644 --- a/app/pages/guides/project-structure.wrn +++ b/app/pages/guides/project-structure.wrn @@ -7,10 +7,10 @@ page Projectstructure { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Project structure

Pages, components, layouts, APIs, middleware, schemas, database files, locales, realtime rooms, and styles live under app. Never edit app/routes.gen.ts, .wrnexus, or dist by hand.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Project structure

Pages, components, layouts, APIs, middleware, schemas, database files, locales, realtime rooms, and styles live under app. Never edit app/routes.gen.ts, .wrnexus, or dist by hand.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/pubsub.wrn b/app/pages/guides/pubsub.wrn index 418e8641..a59db8a9 100644 --- a/app/pages/guides/pubsub.wrn +++ b/app/pages/guides/pubsub.wrn @@ -7,10 +7,10 @@ page Pubsub { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Pub/sub

The in-process driver cannot cross processes. Use Redis where instances must share events, define channel ownership, and design for reconnects and duplicate delivery.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Pub/sub

The in-process driver cannot cross processes. Use Redis where instances must share events, define channel ownership, and design for reconnects and duplicate delivery.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/queues.wrn b/app/pages/guides/queues.wrn index 022e93bb..3b6c39e5 100644 --- a/app/pages/guides/queues.wrn +++ b/app/pages/guides/queues.wrn @@ -7,10 +7,10 @@ page Queues { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Queues

Queue behavior is preview-level. Treat in-process work as non-durable, make handlers idempotent, cap retries, record failures, and choose a production persistence strategy.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Queues

Queue behavior is preview-level. Treat in-process work as non-durable, make handlers idempotent, cap retries, record failures, and choose a production persistence strategy.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/realtime.wrn b/app/pages/guides/realtime.wrn index b0ce9f6b..2235e5cc 100644 --- a/app/pages/guides/realtime.wrn +++ b/app/pages/guides/realtime.wrn @@ -7,10 +7,10 @@ page Realtime { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Realtime

defineRoom handles connection and messages. Validate message shapes, authorize subscriptions, restrict origins, bound payloads, and use pub/sub to scale across processes.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Realtime

defineRoom handles connection and messages. Validate message shapes, authorize subscriptions, restrict origins, bound payloads, and use pub/sub to scale across processes.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/routing.wrn b/app/pages/guides/routing.wrn index 141e0b1b..a86e7dd7 100644 --- a/app/pages/guides/routing.wrn +++ b/app/pages/guides/routing.wrn @@ -7,10 +7,10 @@ page Routing { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Routing

A page filename defines its URL; index maps to the directory root and bracket segments are dynamic parameters. API files under app/api expose HTTP method functions and receive a Context.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Routing

A page filename defines its URL; index maps to the directory root and bracket segments are dynamic parameters. API files under app/api expose HTTP method functions and receive a Context.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/security.wrn b/app/pages/guides/security.wrn index e710e3ff..1c51da6e 100644 --- a/app/pages/guides/security.wrn +++ b/app/pages/guides/security.wrn @@ -7,10 +7,10 @@ page Applicationsecurity { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Application security

Use CSP, CSRF, Trusted Types, session hardening, validation, origin checks, upload restrictions, encryption, request limits, and explicit CORS. See the security policy for reporting.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Application security

Use CSP, CSRF, Trusted Types, session hardening, validation, origin checks, upload restrictions, encryption, request limits, and explicit CORS. See the security policy for reporting.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/server-data.wrn b/app/pages/guides/server-data.wrn index 126ba688..94b1b65f 100644 --- a/app/pages/guides/server-data.wrn +++ b/app/pages/guides/server-data.wrn @@ -7,10 +7,10 @@ page Serverdata { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Server data

Use an ssr API binding, return the desired response field, and render it with a server #each block. Values are escaped. Avoid fetching private data through a route that lacks authorization.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Server data

Use an ssr API binding, return the desired response field, and render it with a server #each block. Values are escaped. Avoid fetching private data through a route that lacks authorization.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/testing.wrn b/app/pages/guides/testing.wrn index cf8762e7..b55f25af 100644 --- a/app/pages/guides/testing.wrn +++ b/app/pages/guides/testing.wrn @@ -7,10 +7,10 @@ page Testing { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Testing

Use Bun tests and @wrnexus/test helpers. Cover server HTML, API status and validation, authorization failures, reactive behavior, and a production startup smoke test.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Testing

Use Bun tests and @wrnexus/test helpers. Cover server HTML, API status and validation, authorization failures, reactive behavior, and a production startup smoke test.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/troubleshooting.wrn b/app/pages/guides/troubleshooting.wrn index b6124b15..736bb579 100644 --- a/app/pages/guides/troubleshooting.wrn +++ b/app/pages/guides/troubleshooting.wrn @@ -7,10 +7,10 @@ page Troubleshooting { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Troubleshooting

Confirm Bun and package versions, regenerate docs/routes through supported commands, read the first compiler diagnostic, check file naming, validate config, and reproduce under a production build.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Troubleshooting

Confirm Bun and package versions, regenerate docs/routes through supported commands, read the first compiler diagnostic, check file naming, validate config, and reproduce under a production build.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/upgrading.wrn b/app/pages/guides/upgrading.wrn index 81138162..fcb8b159 100644 --- a/app/pages/guides/upgrading.wrn +++ b/app/pages/guides/upgrading.wrn @@ -7,10 +7,10 @@ page Upgrading { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Upgrading

Back up and commit first, then use wrnexus update --latest as documented by the installed CLI. Review migrations and keep every @wrnexus package aligned. Current release: 0.8.4.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Upgrading

Back up and commit first, then use wrnexus update --latest as documented by the installed CLI. Review migrations and keep every @wrnexus package aligned. Current release: 0.8.5.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/uploads.wrn b/app/pages/guides/uploads.wrn index d564952f..14b8dd51 100644 --- a/app/pages/guides/uploads.wrn +++ b/app/pages/guides/uploads.wrn @@ -7,10 +7,10 @@ page Uploads { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Uploads

Configure named stores, accepted MIME/extensions, and maxBytes. Random keys avoid path traversal. Private files require an authenticated serving route; v1 buffers each file in memory.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.5

Uploads

Configure named stores, accepted MIME/extensions, and maxBytes. Random keys avoid path traversal. Private files require an authenticated serving route; v1 buffers each file in memory.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/guides/workspaces-and-gateway.wrn b/app/pages/guides/workspaces-and-gateway.wrn index bb274956..9cc4404e 100644 --- a/app/pages/guides/workspaces-and-gateway.wrn +++ b/app/pages/guides/workspaces-and-gateway.wrn @@ -7,9 +7,9 @@ page Workspacesandgateway { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.8.4

Workspaces and gateway

A workspace runs isolated applications behind one domain-routing gateway. Add an application from the workspace root; the CLI scaffolds apps/reports and registers it in wrnexus.workspace.ts:

wrnexus workspace add reports --domain=reports.localhost
+      
Preview guide · 0.8.5

Workspaces and gateway

A workspace runs isolated applications behind one domain-routing gateway. Add an application from the workspace root; the CLI scaffolds apps/reports and registers it in wrnexus.workspace.ts:

wrnexus workspace add reports --domain=reports.localhost
 bun install
 bun run dev

Forward authentication

Point protected applications at a dedicated verifier endpoint. The verifier must return 2xx for an authenticated session, 401/403 to deny access, or an HTTP redirect to begin browser login.

// wrnexus.workspace.ts
 {
@@ -28,8 +28,8 @@ export const GET = async (ctx: Context) => {
   return redirectToLogin(ctx, "/login", {
     allowedHosts: ["admin.localhost:3000", "reports.localhost:3000"],
   });
-};

Always allowlist redirect hosts. After login, validate or sign the returnTo value before redirecting. Keep internal app ports private and open applications through the gateway port.

Release scope

This guide describes installed 0.8.4 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +};

Always allowlist redirect hosts. After login, validate or sign the returnTo value before redirecting. Keep internal app ports private and open applications through the gateway port.

Release scope

This guide describes installed 0.8.5 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} } \ No newline at end of file diff --git a/app/pages/index.wrn b/app/pages/index.wrn index 8dd5e7c2..3ea9a16c 100644 --- a/app/pages/index.wrn +++ b/app/pages/index.wrn @@ -7,9 +7,9 @@ page Home { view {
-
W WRNexusJS
+
W WRNexusJS
-

WRNexusJS v0.8.4

Build from the server.
Ship only what matters.

WRNexusJS is an SSR-first, Bun-native full-stack framework. Build typed pages, APIs, validated forms, realtime rooms, secure sessions, workspaces, and optional mobile experiences with the .wrn component language.

Private developer preview. Request access to the package registry.

app/pages/dashboard.wrn
page Dashboard {
+      

WRNexusJS v0.8.5

Build from the server.
Ship only what matters.

WRNexusJS is an SSR-first, Bun-native full-stack framework. Build typed pages, APIs, validated forms, realtime rooms, secure sessions, workspaces, and optional mobile experiences with the .wrn component language.

Private developer preview. Request access to the package registry.

app/pages/dashboard.wrn
page Dashboard {
   ssr { api tasks GET /api/tasks { return tasks } }
   view {
     <main>
@@ -35,10 +35,10 @@ export const POST = async (ctx) => {
   return result.ok ? Response.json({ ok: true }, { status: 201 }) : result.response;
 };

Request lifecycle

  1. RequestSecurity headers and request limits
  2. MiddlewareAuthentication, policy, and context
  3. File routePage or API handler
  4. Compiler + SSRSafe HTML and scoped runtime
  5. ResponseHTML, JSON, stream, or realtime upgrade
-

Production proof

WorkRoot

Public creator/company site and approved WRNexusJS production showcase.

wrnexusjs.dev

This documentation application runs WRNexusJS 0.8.4.

View deployment notes and showcase status →

-

Capability status

CapabilityStatusDetails
SSR, routing, compiler, APIsPreviewInstalled in 0.8.4; public support policy pending.
Mobile/nativeExperimentalCapacitor compatibility and native generation have platform limitations.
Durable queuesExperimentalProduction durability requires an appropriate driver strategy.
-

Continue exploring

- +

Production proof

WorkRoot

Public creator/company site and approved WRNexusJS production showcase.

wrnexusjs.dev

This documentation application runs WRNexusJS 0.8.5.

View deployment notes and showcase status →

+

Capability status

CapabilityStatusDetails
SSR, routing, compiler, APIsPreviewInstalled in 0.8.5; public support policy pending.
Mobile/nativeExperimentalCapacitor compatibility and native generation have platform limitations.
Durable queuesExperimentalProduction durability requires an appropriate driver strategy.
+

Continue exploring

+
} } \ No newline at end of file diff --git a/app/pages/language.wrn b/app/pages/language.wrn index 1b06f99e..469d7c5c 100644 --- a/app/pages/language.wrn +++ b/app/pages/language.wrn @@ -7,15 +7,15 @@ page Thewrnlanguage { view {
-
W WRNexusJS
+
W WRNexusJS
-
Language reference · 0.8.4

The .wrn language

File anatomy

page Account {
+      
Language reference · 0.8.5

The .wrn language

File anatomy

page Account {
   layout = "public"
   seo { title = "Account" description = "Manage your account." }
   state count = 0
   view { <button @click="count++">Count {count}</button> }
 }

Pages, components, layouts, props, and state

Pages are routes. Components declare default-valued props and may hold state. Layouts provide shared slots. Mount components with data-component; fill default or named slots with data-slot.

Interpolation, conditionals, and loops

Interpolation is HTML-escaped. Use server {#if} and {#each} for SSR data. Use data-show for reactive client visibility.

Events and directives

@click and other events execute in the reactive scope. Data attributes opt into forms, i18n, themes, realtime, uploader, browser, and mobile behavior. Consult the exact package page because availability varies.

Forms, i18n, themes, and realtime

form[data-schema] connects descriptors to client and server validation. Translation keys use {t:key}. Theme toggles use data-wire-theme-toggle. Realtime pages opt into a named room.

Escaping and security

Text interpolation is escaped by default. Do not construct trusted HTML from user input. Server-only refinements must be repeated at the authoritative mutation boundary.

Common compiler errors

  • Use balanced braces; a literal brace must be escaped.
  • Declare UI in view, not JSX or hooks.
  • Use a valid page, component, or layout declaration matching the file role.
  • Keep server loops tied to available SSR bindings.
  • Check troubleshooting and compiler API for this release.
- +
} } \ No newline at end of file diff --git a/app/pages/license.wrn b/app/pages/license.wrn index cdb5edb2..b33a5499 100644 --- a/app/pages/license.wrn +++ b/app/pages/license.wrn @@ -7,10 +7,10 @@ page License { view {
-
W WRNexusJS
+
W WRNexusJS

License

Owner decision required

This documentation repository contains no public license file, and the packages are unavailable from the public npm registry. No open-source license or redistribution right should be inferred.

Approved preview users must follow the private/commercial terms supplied by WorkRoot. Contact WorkRoot before copying, redistributing, or using WRNexusJS in production.

- +
} } \ No newline at end of file diff --git a/app/pages/packages.wrn b/app/pages/packages.wrn index a071e2ae..87908a60 100644 --- a/app/pages/packages.wrn +++ b/app/pages/packages.wrn @@ -12,10 +12,10 @@ page Packages {
W WRNexusJS - +
-
46 focused packages

Package reference

Everything in the framework, organized by responsibility and documented from the published 0.8.4 APIs.

Showing {category} packages

+
46 focused packages

Package reference

Everything in the framework, organized by responsibility and documented from the published 0.8.5 APIs.

Showing {category} packages

AI

@wrnexus/ai

Server-side Anthropic client with generation and streaming.

Open documentation →
@@ -153,7 +153,7 @@ page Packages { Security

@wrnexus/validation

Typed schemas, coercion, validation, and browser descriptors.

Open documentation →
- + } } diff --git a/app/pages/packages/ai.wrn b/app/pages/packages/ai.wrn index c54f4821..6b1e276a 100644 --- a/app/pages/packages/ai.wrn +++ b/app/pages/packages/ai.wrn @@ -10,11 +10,11 @@ page wrnexusai {
W WRNexusJS - +
-
AI · Package reference

@wrnexus/ai

Server-side Anthropic client with generation and streaming.

v0.8.4Private registryAI

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/ai@0.8.4

Request preview access. Never put registry tokens in source control.

Provider-neutral AI orchestration for OpenAI, Anthropic, Google and local OpenAI-compatible models, with streaming, structured output, tools, embeddings, vector search/RAG, conversation persistence, templates, guardrails, usage events, fallback, rate limits and evaluation reports.

+
AI · Package reference

@wrnexus/ai

Server-side Anthropic client with generation and streaming.

v0.8.5Private registryAI

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/ai@0.8.5

Request preview access. Never put registry tokens in source control.

Provider-neutral AI orchestration for OpenAI, Anthropic, Google and local OpenAI-compatible models, with streaming, structured output, tools, embeddings, vector search/RAG, conversation persistence, templates, guardrails, usage events, fallback, rate limits and evaluation reports.

A tiny, zero-dependency Claude (Anthropic) client for WRNexusJS apps — generate and stream text with Claude from any server-side code.

Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

Overview

@@ -151,7 +151,7 @@ export const POST = async (ctx) => { };
- + } } diff --git a/app/pages/packages/auth.wrn b/app/pages/packages/auth.wrn index ead22963..4d0193b7 100644 --- a/app/pages/packages/auth.wrn +++ b/app/pages/packages/auth.wrn @@ -10,11 +10,11 @@ page wrnexusauth {
W WRNexusJS - +
-
Security · Package reference

@wrnexus/auth

Authentication routes, sessions, forms, guards, and account flows.

v0.8.4Private registrySecurity

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/auth@0.8.4

Request preview access. Never put registry tokens in source control.

Framework-native authentication, identity, account-security, and session management for WRNexusJS.

+
Security · Package reference

@wrnexus/auth

Authentication routes, sessions, forms, guards, and account flows.

v0.8.5Private registrySecurity

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/auth@0.8.5

Request preview access. Never put registry tokens in source control.

Framework-native authentication, identity, account-security, and session management for WRNexusJS.

Capabilities

  • Password registration, login, recovery, reset, and authenticated password changes
  • @@ -287,7 +287,7 @@ export { A as AUTH_SECURITY_EVENT_TYPES, a as AuthAccountStatus, b as AuthC export { MemoryAuthStore } from './stores/memory.js'; export { SqlAuthStore } from './stores/sql.js'; export { AUTH_SESSION_KEY, authSession, clearAuthSession, establishAuthSession, getAuthSession, getAuthUser, isAuthenticatedContext, requireAuth } from './middleware.js'; -export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-B4uaD0Z3.js'; +export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-BuZlwKSF.js'; export { AuthAuditIssue, AuthConfig, AuthPluginOptions, AuthRoutesConfig, authComponentsDir, authPlugin } from './plugin.js'; export { DefaultAuthRouteOptions, clearDefaultAuthEngine, getDefaultAuthEngine, getDefaultAuthRouteOptions, getDefaultAuthSchemas, hasDefaultAuthEngine, setDefaultAuthEngine, setDefaultAuthRouteOptions, setDefaultAuthSchemas, tryGetDefaultAuthEngine } from './runtime.js'; export { createAuthSecretProtector } from './protector.js'; @@ -386,7 +386,7 @@ export const auth = createAuthEngine({ };
- + } } diff --git a/app/pages/packages/authz.wrn b/app/pages/packages/authz.wrn index 6a9b4a0c..8ebe7da1 100644 --- a/app/pages/packages/authz.wrn +++ b/app/pages/packages/authz.wrn @@ -10,11 +10,11 @@ page wrnexusauthz {
W WRNexusJS - +
-
Security · Package reference

@wrnexus/authz

Role, permission, policy, and authorization guards.

v0.8.4Private registrySecurity

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/authz@0.8.4

Request preview access. Never put registry tokens in source control.

Composable authorization for WRNexusJS — role-based (RBAC), policy-based (PBAC), and attribute-based (ABAC) access control that reduces to a boolean check plus an authorize() guard.
+
Security · Package reference

@wrnexus/authz

Role, permission, policy, and authorization guards.

v0.8.5Private registrySecurity

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/authz@0.8.5

Request preview access. Never put registry tokens in source control.

Composable authorization for WRNexusJS — role-based (RBAC), policy-based (PBAC), and attribute-based (ABAC) access control that reduces to a boolean check plus an authorize() guard.

Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

Overview

@wrnexus/authz is a small, server-side authorization toolkit. It gives you three interchangeable models — RBAC (roles → permissions), PBAC (policy predicates), and ABAC (attribute matchers) — that all collapse to a boolean | Promise<boolean> decision. Wrap any decision in a Middleware guard (authorize, requireRole, requirePermission) to protect WRNexusJS routes. Reach for it whenever a route or action needs to be gated on who the user is, what roles they hold, or attributes of the user and the resource. It plugs into @wrnexus/core by reading ctx.user as the authorization subject.

@@ -122,23 +122,260 @@ app.put(
  • Bun-only — like the rest of WRNexusJS, this package targets the Bun runtime; Node is not supported.
  • Works with [@wrnexus/core](../core) — the guards return Middleware and read the subject from ctx.user on the request Context. Both types are imported from @wrnexus/core.
  • Policy combinators (any, all) and authorize are async-aware, so policies may return a Promise<boolean> (e.g. for a database ownership check).
  • -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context, Middleware } from '@wrnexus/core';
    +
    +

    Declaring permissions

    +

    The RBAC/PBAC/ABAC surface above is the low-level toolkit. On top of it sits a declarative registry + catalog + store + engine: permissions, roles, and policies are declared once in code, merged into a frozen catalog at boot, and resolved per-request against a pluggable PermissionStore that holds who has what.

    +

    Put declarations in app/authz/<name>.ts; they are discovered automatically and merged (conflicting declarations of the same permission/role/policy across files fail the boot loudly, naming both source files).

    +
    import { defineAuthz, owner } from "@wrnexus/authz";
     
    -interface AuthorizationDecision {
    +export default defineAuthz({
    +  permissions: {
    +    "post:read": { title: "View posts", public: true },
    +    "post:delete": { title: "Delete posts", risk: "high" },
    +  },
    +  // "post:*" is a namespace wildcard grant, valid inside a role's list — it is
    +  // not itself a registered permission, so it can only ever grant permissions
    +  // that ARE declared above (e.g. "post:read", "post:delete").
    +  roles: { editor: ["post:*"], admin: ["role:editor"] },
    +  policies: { ownsPost: owner("id", "authorId") },
    +  bindings: { "post:delete": ["ownsPost"] },
    +});
    +

    public: true means anonymous callers may hold the permission — but any policy bound to it still runs, and can still veto the anonymous caller (e.g. a notBanned policy on a public post:preview permission).

    +

    Checking permissions

    +

    Register authzMiddleware once, in app/middleware/, with the merged catalog and a PermissionStore. Like every other app/middleware/*.ts file, the registration is an eager, module-scope call — the same shape as authzMiddleware({ catalog, store }) requires — so it must run after the catalog has been populated. Both the dev server and wrnexus build's generated production entry guarantee getAuthzCatalog() is populated before any app middleware module evaluates. Name the file so it sorts after whatever middleware sets ctx.user (middleware runs in alphabetical filename order — authz.ts after auth.ts, for instance).

    +
    // app/middleware/authz.ts
    +import { authzMiddleware, getAuthzCatalog } from "@wrnexus/authz";
    +import { dbPermissionStore } from "@wrnexus/authz/db";
    +import { getDb } from "@wrnexus/db";
    +
    +export default authzMiddleware({ catalog: getAuthzCatalog(), store: dbPermissionStore(getDb()) });
    +
    subject.id must be a non-empty string. The engine denies (and logs to
    +
    stderr) whenever ctx.user.id is present but not a non-empty string — this
    +
    includes the common case of an integer primary key. Coerce it before it
    +
    reaches ctx.user, e.g. user.id = String(row.id), or every request for
    +
    that user denies with "Invalid subject" instead of resolving normally.
    +
    owner() (the built-in ownership policy) compares subject and resource ids
    +
    with Object.is, so both sides must be the same type too — owner() on a
    +
    numeric resource.authorId against a stringified subject.id never
    +
    matches even when they represent "the same" id.
    +

    There is no per-route middleware export — app/middleware/*.ts is the only place middleware is registered. To gate part of the app, branch on the request the same way any other conditional middleware does (compare app/middleware/captcha-login.ts in the auth showcase, which branches on method + path the same way):

    +
    // app/middleware/protect-posts.ts
    +import type { Context, Next } from "@wrnexus/core";
    +import { guardPermission } from "@wrnexus/authz";
    +
    +const guardPostWrite = guardPermission("post:write");
    +
    +export default function protectPosts(ctx: Context, next: Next) {
    +  return ctx.url.pathname.startsWith("/api/posts") && ctx.req.method !== "GET"
    +    ? guardPostWrite(ctx, next)
    +    : next();
    +}
    +

    Or check inline inside a route handler with the free function can():

    +
    // app/api/posts/[id].ts
    +import type { Context } from "@wrnexus/core";
    +import { can } from "@wrnexus/authz";
    +
    +export const DELETE = async (ctx: Context) => {
    +  const post = { id: "1", authorId: "alice" }; // load your own resource here
    +  if (!(await can(ctx, "post:delete", post))) {
    +    return Response.json({ ok: false, error: "Forbidden" }, { status: 403 });
    +  }
    +  return Response.json({ ok: true });
    +};
    +

    can() is a free function taking ctx, not ctx.can@wrnexus/core must not depend on @wrnexus/authz, so the per-request resolver lives in ctx.locals instead, reached through can() / decideFor() / guardPermission() / filterCan(). Calling any of them before authzMiddleware has run for that request throws a WRN-AUTHZ-SETUP error naming the missing registration, rather than silently denying.

    +

    See examples/auth-showcase/app/authz/showcase.ts and examples/auth-showcase/app/middleware/authz.ts for a complete, runnable version of this wiring.

    +

    Precedence

    +

    1. An explicit deny wins over everything, including * — and honours the same namespace-wildcard matching as grants (denying post:* blocks post:comment:delete, not just post:* itself). 2. A bound policy can veto a permission a role grants, and runs even for a public: true permission — including for an anonymous caller. 3. Otherwise the permission must be held via a role or an explicit grant. 4. Default deny.

    +

    Every failure — an unknown permission (outside strict/dev mode), a store outage, a thrown policy — denies rather than throwing through to the caller.

    +

    permissionsFor() (on the resolver returned by createAuthzResolver) is a coarse hint for hiding UI (e.g. a menu section), never authoritative. A Set<string> cannot represent "granted post:* except post:delete", so a narrow deny beneath a broad grant is invisible to it — the set still contains post:* while can() / decide() correctly refuse post:delete. Gate real actions with can(), decideFor(), or filterCan(); never by matching against permissionsFor()'s result.

    +

    CLI

    +
    wrnexus authz list      # every registered permission, role, and policy
    +wrnexus authz generate  # app/authz/permissions.gen.ts type unions
    +wrnexus authz init      # scaffold the assignment-table migration
    +

    wrnexus authz generate's output is a plain Permission | Role string-literal union — can(), guardPermission(), and decideFor() all take a bare string and nothing reads this file automatically, so import it to type your own helpers/constants against the registered catalog, e.g.:

    +
    import type { Permission } from "app/authz/permissions.gen.ts";
    +
    +function guard(permission: Permission) {
    +  return guardPermission(permission);
    +}

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context, Middleware } from '@wrnexus/core';
    +
    +/**
    + * Validate and freeze one authorization declaration. Called from
    + * `app/authz/<name>.ts` as the module's default export.
    + */
    +declare function defineAuthz(module: AuthzModule): AuthzModule;
    +
    +interface CatalogSource {
    +    /** File or package that declared this module, used in conflict messages. */
    +    source: string;
    +    module: AuthzModule;
    +}
    +declare function emptyCatalog(): AuthzCatalog;
    +declare function mergeCatalogs(sources: CatalogSource[]): AuthzCatalog;
    +
    +/**
    + * A process-wide authorization catalog registry, mirroring `@wrnexus/db`'s
    + * `client.ts` (`setDb`/`getDb`/`hasDb`). It exists for the same reason: app
    + * middleware runs at module-eval time — `app/middleware/*.ts` registers
    + * `authzMiddleware({ catalog, store, ... })` itself, an EAGER call (the same
    + * shape as `logger.ts`'s `export default requestLogger({...})`), and it needs
    + * the merged catalog *then*, before its own module body finishes running.
    + * Passing it through `ctx` does not work at that point, so the framework
    + * loads and merges every `app/authz/*.ts` declaration and stashes it here
    + * before any other module can observe it:
    + *
    + *  - dev: `startServer` calls `loadAppAuthzCatalog` + `setAuthzCatalog`
    + *    before middleware is resolved.
    + *  - prod (the normal `wrnexus build` output): the generated entry statically
    + *    imports a small `.authz-setup.ts` module FIRST — before any page, API,
    + *    or middleware import — which calls `setAuthzCatalog` at ITS OWN module
    + *    scope. ES modules evaluate every static import before the importing
    + *    module's body runs, and evaluate sibling imports in declaration order,
    + *    so import position is evaluation order: this guarantees the catalog
    + *    exists before app middleware's own module body (which may read it
    + *    eagerly) ever evaluates. `createProductionHandlers` (`prod.ts`) then
    + *    repeats the merge as an idempotent second pass, mainly so a caller who
    + *    bypasses the generated entry and invokes it directly still gets a
    + *    catalog — for THAT path specifically, an eager module-scope read in
    + *    middleware is only safe if the caller sets the catalog before importing
    + *    the middleware itself, since no generated `.authz-setup.ts` runs first.
    + *
    + * The framework never installs `authzMiddleware` itself — the app always
    + * chooses its own store and registers the middleware; this registry only
    + * makes the merged catalog reachable when it does.
    + */
    +
    +/** Set the process-wide authorization catalog (called by the framework at boot). */
    +declare function setAuthzCatalog(next: AuthzCatalog): AuthzCatalog;
    +/** The process-wide authorization catalog. Throws if it hasn't been set. */
    +declare function getAuthzCatalog(): AuthzCatalog;
    +/** Whether the process-wide authorization catalog has been set. */
    +declare function hasAuthzCatalog(): boolean;
    +
    +interface AuthzAuditEvent {
    +    subjectId?: string;
    +    scope?: AuthzScope;
    +    permission: string;
         allowed: boolean;
         reason?: string;
         policy?: string;
    -    metadata?: Record<string, unknown>;
    +    /** Epoch milliseconds. */
    +    at: number;
     }
    -type DecisionPolicy<S = Subject, R = unknown> = (subject: S, resource?: R) => AuthorizationDecision | Promise<AuthorizationDecision>;
    -declare function allow(reason?: string, metadata?: Record<string, unknown>): AuthorizationDecision;
    -declare function deny(reason?: string, metadata?: Record<string, unknown>): AuthorizationDecision;
    -declare function decision<S, R>(name: string, policy: Policy<S, R>, denial?: string): DecisionPolicy<S, R>;
    -declare function owner<SubjectType extends Subject, Resource extends Record<string, unknown>>(subjectKey?: keyof SubjectType, resourceKey?: keyof Resource | string): DecisionPolicy<SubjectType, Resource>;
    -declare function anyDecision<S, R>(...policies: DecisionPolicy<S, R>[]): DecisionPolicy<S, R>;
    -declare function allDecisions<S, R>(...policies: DecisionPolicy<S, R>[]): DecisionPolicy<S, R>;
    -declare function authorizeDecision(evaluate: (ctx: Context) => AuthorizationDecision | Promise<AuthorizationDecision>): Middleware;
    -declare function filterAuthorized<S, R>(subject: S, values: readonly R[], policy: Policy<S, R>): Promise<R[]>;
    +interface AuthzAuditSink {
    +    record(event: AuthzAuditEvent): void | Promise<void>;
    +}
    +interface MemoryAuditSink extends AuthzAuditSink {
    +    events: AuthzAuditEvent[];
    +    clear(): void;
    +}
    +declare function memoryAuditSink(): MemoryAuditSink;
    +declare function consoleAuditSink(): AuthzAuditSink;
    +/** Record without ever letting a sink failure escape into the request path. */
    +declare function safeRecord(sink: AuthzAuditSink | undefined, event: AuthzAuditEvent): void;
    +
    +interface AuthzResolverOptions {
    +    catalog: AuthzCatalog;
    +    store: PermissionStore;
    +    audit?: AuthzAuditSink;
    +    /**
    +     * Throw on an unregistered permission instead of denying. Defaults to true
    +     * outside production, so typos surface during development.
    +     */
    +    strict?: boolean;
    +    /** Record allows as well as denies. Off by default to bound write volume. */
    +    auditAllows?: boolean;
    +}
    +interface DecideInput {
    +    subject: {
    +        id?: string;
    +        [key: string]: unknown;
    +    } | null | undefined;
    +    permission: string;
    +    resource?: unknown;
    +    scope?: AuthzScope;
    +}
    +interface AuthzResolver {
    +    /**
    +     * Effective permissions with denied entries removed — for coarse gating such
    +     * as hiding a menu section.
    +     *
    +     * NOT authoritative. A set of strings cannot express "everything under
    +     * `post:*` except `post:delete`", so a narrow deny beneath a broad grant is
    +     * not representable here: the set still contains `post:*` while `decide()`
    +     * correctly refuses `post:delete`. Gate individual actions with `decide()`
    +     * (or `can()` / `filterCan()`), never by matching against this set.
    +     */
    +    permissionsFor(subjectId: string, scope?: AuthzScope): Promise<Set<string>>;
    +    decide(input: DecideInput): Promise<AuthorizationDecision>;
    +}
    +/** Expand roles into their granted entries, following `role:` and stopping on cycles. */
    +declare function expandRoles(catalog: AuthzCatalog, roles: readonly string[]): Set<string>;
    +/**
    + * Exact match, root wildcard, or a namespace wildcard at any depth.
    + *
    + * Do NOT gate access by matching against `permissionsFor()`'s result — that set
    + * cannot represent a narrow deny beneath a broad grant, so the composition
    + * returns true where `decide()` refuses. Use `decide()` / `can()` instead.
    + */
    +declare function permissionMatches(granted: Set<string>, permission: string): boolean;
    +/**
    + * True if any entry in the deny list covers `permission`. Denies honour the
    + * same depth-aware wildcards as grants, so denying "post:*" blocks
    + * post:comment:delete rather than being accepted and silently doing nothing.
    + */
    +declare function deniedBy(denies: readonly string[], permission: string): boolean;
    +declare function createAuthzResolver(options: AuthzResolverOptions): AuthzResolver;
    +
    +/**
    + * `can` is deliberately not a Context member: @wrnexus/core must not depend on
    + * @wrnexus/authz. The per-request resolver lives here instead.
    + */
    +declare const AUTHZ_LOCALS_KEY = "_authz";
    +/** Install the per-request resolver. Register early, after sessionAuth. */
    +declare function authzMiddleware(options: AuthzResolverOptions): Middleware;
    +/**
    + * Object resources are memoised by identity (`byRef`), never by serialising
    + * their contents — serialisation is what let unrelated resources collide
    + * (same `id` shape, circular references, BigInt fields, throwing getters all
    + * funnelled into one bucket). Symbols are memoised by identity too (`bySymbol`)
    + * since `String(symbol)` collapses distinct symbols with the same description.
    + * Primitive/absent resources are memoised by a
    + * `[scope, permission, typeof, String(value)]` tuple, with `-0` rendered
    + * distinctly from `0` since `String(-0) === "0"` would otherwise merge them.
    + *
    + * Subject and scope are both part of the key. A request that reassigns
    + * ctx.user (impersonation, step-up auth, session revocation) or ctx.tenant
    + * must not be served the previous principal's verdict from the memo.
    + */
    +declare function decideFor(ctx: Context, permission: string, resource?: unknown): Promise<AuthorizationDecision>;
    +declare function can(ctx: Context, permission: string, resource?: unknown): Promise<boolean>;
    +interface GuardOptions {
    +    /** Load the resource a bound policy needs. */
    +    getResource?: (ctx: Context) => unknown;
    +    /** Include reason and policy name in the 403 body. Off by default. */
    +    exposeReason?: boolean;
    +    /** Redirect page requests here instead of returning 403. Ignored for JSON/API requests and for any non-local target. */
    +    redirectTo?: string;
    +}
    +/**
    + * Guard a route on a registered permission. Named `guardPermission` because
    + * `requirePermission(rbac, permission)` already exists with a different shape.
    + */
    +declare function guardPermission(permission: string, options?: GuardOptions): Middleware;
    +/** Keep only the items the current subject may act on. */
    +declare function filterCan<T>(ctx: Context, permission: string, items: readonly T[]): Promise<T[]>;
    +
    +/**
    + * Emit `Permission`/`Role` string-literal unions from the registered catalog.
    + *
    + * This does NOT make `can(ctx, "post:wrtie")` a type error — `can()`,
    + * `guardPermission()`, and `decideFor()` all take a bare `string`, and
    + * nothing in the framework consumes this generated file automatically.
    + * Import the unions yourself to type your OWN helpers/constants, e.g.
    + * `const PERM: Permission = "post:write"` or a typed wrapper around `can()`.
    + */
    +declare function generatePermissionTypes(catalog: AuthzCatalog): string;
     
     /**
      * @wrnexus/authz — authorization: role-based (RBAC), policy-based (PBAC), and
    @@ -183,7 +420,108 @@ declare function requireRole(...roles: string[]): Middleware;
     /** Guard requiring an RBAC permission. */
     declare function requirePermission(rbac: Rbac, permission: string): Middleware;
     
    -export { type AuthorizationDecision, type DecisionPolicy, type Policy, type Rbac, type Subject, all, allDecisions, allow, any, anyDecision, attr, authorize, authorizeDecision, decision, defineRbac, deny, filterAuthorized, hasRole, owner, requirePermission, requireRole };
    +interface AuthorizationDecision {
    +    allowed: boolean;
    +    reason?: string;
    +    policy?: string;
    +    metadata?: Record<string, unknown>;
    +}
    +type DecisionPolicy<S = Subject, R = unknown> = (subject: S, resource?: R) => AuthorizationDecision | Promise<AuthorizationDecision>;
    +declare function allow(reason?: string, metadata?: Record<string, unknown>): AuthorizationDecision;
    +declare function deny(reason?: string, metadata?: Record<string, unknown>): AuthorizationDecision;
    +declare function decision<S, R>(name: string, policy: Policy<S, R>, denial?: string): DecisionPolicy<S, R>;
    +declare function owner<SubjectType extends Subject, Resource extends Record<string, unknown>>(subjectKey?: keyof SubjectType, resourceKey?: keyof Resource | string): DecisionPolicy<SubjectType, Resource>;
    +declare function anyDecision<S, R>(...policies: DecisionPolicy<S, R>[]): DecisionPolicy<S, R>;
    +declare function allDecisions<S, R>(...policies: DecisionPolicy<S, R>[]): DecisionPolicy<S, R>;
    +interface AuthorizeDecisionOptions {
    +    /**
    +     * Include `reason` and `policy` in the 403 body. Off by default: policy
    +     * names describe internal authorization structure and should not reach an
    +     * unauthenticated caller.
    +     */
    +    exposeReason?: boolean;
    +}
    +declare function authorizeDecision(evaluate: (ctx: Context) => AuthorizationDecision | Promise<AuthorizationDecision>, options?: AuthorizeDecisionOptions): Middleware;
    +declare function filterAuthorized<S, R>(subject: S, values: readonly R[], policy: Policy<S, R>): Promise<R[]>;
    +
    +/** Narrows an assignment to a tenant. Absent means a global assignment. */
    +interface AuthzScope {
    +    tenantId?: string;
    +}
    +interface PermissionMeta {
    +    title?: string;
    +    description?: string;
    +    risk?: "low" | "medium" | "high";
    +    /** Granted to anonymous subjects. Every other permission denies without a user. */
    +    public?: boolean;
    +}
    +interface AttributeMeta {
    +    description?: string;
    +}
    +/** One `app/authz/<name>.ts` declaration. */
    +interface AuthzModule {
    +    permissions?: Record<string, PermissionMeta>;
    +    roles?: Record<string, string[]>;
    +    policies?: Record<string, DecisionPolicy<never, never>>;
    +    attributes?: Record<string, AttributeMeta>;
    +    /** permission id -> policy names that must pass for it. */
    +    bindings?: Record<string, string[]>;
    +}
    +/** The merged, frozen view of every declaration in the app. */
    +interface AuthzCatalog {
    +    permissions: ReadonlyMap<string, PermissionMeta>;
    +    roles: ReadonlyMap<string, readonly string[]>;
    +    policies: ReadonlyMap<string, DecisionPolicy<never, never>>;
    +    attributes: ReadonlyMap<string, AttributeMeta>;
    +    bindings: ReadonlyMap<string, readonly string[]>;
    +}
    +interface SubjectAssignments {
    +    roles: string[];
    +    /** Explicit allows, bypassing roles. */
    +    grants: string[];
    +    /** Explicit denies. Win over everything, including "*". */
    +    denies: string[];
    +}
    +
    +type GrantEffect = "allow" | "deny";
    +interface PermissionStore {
    +    assignmentsFor(subjectId: string, scope?: AuthzScope): Promise<SubjectAssignments>;
    +    assignRole(subjectId: string, role: string, scope?: AuthzScope): Promise<void>;
    +    revokeRole(subjectId: string, role: string, scope?: AuthzScope): Promise<void>;
    +    grant(subjectId: string, permission: string, effect: GrantEffect, scope?: AuthzScope): Promise<void>;
    +    revokeGrant(subjectId: string, permission: string, scope?: AuthzScope): Promise<void>;
    +    listSubjects(scope?: AuthzScope): Promise<string[]>;
    +}
    +/**
    + * Global assignments are stored under the empty-string scope key. An OMITTED
    + * scope means global; an explicitly EMPTY or non-string tenantId is refused,
    + * because an empty string is indistinguishable from global (and would let a
    + * caller who controls the tenant id read and write global assignments), and a
    + * non-string value (e.g. `null` from a JSON body or a nullable column) would
    + * otherwise flow through un-normalised and leave the adapters disagreeing
    + * about what happened.
    + */
    +declare function scopeKey(scope?: AuthzScope): string;
    +declare function memoryPermissionStore(): PermissionStore;
    +interface CachedPermissionStore extends PermissionStore {
    +    /** Drop one subject. Call after changing roles out of band. */
    +    invalidate(subjectId: string, scope?: AuthzScope): void;
    +    invalidateAll(): void;
    +    /** Cached entry count, for tests and diagnostics. */
    +    size(): number;
    +}
    +interface CacheOptions {
    +    ttlMs?: number;
    +    max?: number;
    +}
    +/**
    + * Caches assignment reads. Writes through this decorator invalidate the
    + * affected subject immediately; changes made directly against the inner store
    + * need an explicit `invalidate()` call rather than waiting out the TTL.
    + */
    +declare function cachedPermissionStore(inner: PermissionStore, options?: CacheOptions): CachedPermissionStore;
    +
    +export { AUTHZ_LOCALS_KEY, type AttributeMeta, type AuthorizationDecision, type AuthorizeDecisionOptions, type AuthzAuditEvent, type AuthzAuditSink, type AuthzCatalog, type AuthzModule, type AuthzResolver, type AuthzResolverOptions, type AuthzScope, type CacheOptions, type CachedPermissionStore, type CatalogSource, type DecideInput, type DecisionPolicy, type GrantEffect, type GuardOptions, type MemoryAuditSink, type PermissionMeta, type PermissionStore, type Policy, type Rbac, type Subject, type SubjectAssignments, all, allDecisions, allow, any, anyDecision, attr, authorize, authorizeDecision, authzMiddleware, cachedPermissionStore, can, consoleAuditSink, createAuthzResolver, decideFor, decision, defineAuthz, defineRbac, deniedBy, deny, emptyCatalog, expandRoles, filterAuthorized, filterCan, generatePermissionTypes, getAuthzCatalog, guardPermission, hasAuthzCatalog, hasRole, memoryAuditSink, memoryPermissionStore, mergeCatalogs, owner, permissionMatches, requirePermission, requireRole, safeRecord, scopeKey, setAuthzCatalog };
     

    Examples

    Copy-ready examples from the installed package documentation.

    RBAC

    import { defineRbac, hasRole } from "@wrnexus/authz";
     
     const rbac = defineRbac({
    @@ -240,9 +578,9 @@ app.put(
       authorize((ctx) => canEdit(ctx.user as User, loadPost(ctx))),
       handler,
     );
    - +
    - + } } diff --git a/app/pages/packages/benchmark.wrn b/app/pages/packages/benchmark.wrn index eef99fc7..115c480a 100644 --- a/app/pages/packages/benchmark.wrn +++ b/app/pages/packages/benchmark.wrn @@ -10,11 +10,11 @@ page wrnexusbenchmark {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/benchmark

    Framework benchmark scenarios and repeatable performance measurements.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/benchmark@0.8.4

    Request preview access. Never put registry tokens in source control.

    Deterministic benchmark execution, percentiles, baseline comparisons, and regression budgets for builds, SSR, hydration, stores, and application hot paths.

    +
    Tooling · Package reference

    @wrnexus/benchmark

    Framework benchmark scenarios and repeatable performance measurements.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/benchmark@0.8.5

    Request preview access. Never put registry tokens in source control.

    Deterministic benchmark execution, percentiles, baseline comparisons, and regression budgets for builds, SSR, hydration, stores, and application hot paths.

    import { runBenchmark, assertBenchmarkBudget } from "@wrnexus/benchmark";
     const result = await runBenchmark("render", render, { iterations: 100 });
     assertBenchmarkBudget(result, baseline, { p95Percent: 5 });

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface BenchmarkOptions {
    @@ -61,7 +61,7 @@ const result = await runBenchmark("render", render, { iterations:
     assertBenchmarkBudget(result, baseline, { p95Percent: 5 });

    Install @wrnexus/benchmark

    bun add @wrnexus/benchmark
    - + } } diff --git a/app/pages/packages/cache.wrn b/app/pages/packages/cache.wrn index 983e8111..9a4369dd 100644 --- a/app/pages/packages/cache.wrn +++ b/app/pages/packages/cache.wrn @@ -10,11 +10,11 @@ page wrnexuscache {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/cache

    Memory and distributed caching with coordination and invalidation.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cache@0.8.4

    Request preview access. Never put registry tokens in source control.

    Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation.

    +
    Data · Package reference

    @wrnexus/cache

    Memory and distributed caching with coordination and invalidation.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cache@0.8.5

    Request preview access. Never put registry tokens in source control.

    Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation.

    import { connectCacheInvalidation, TagCache, responseCache } from "@wrnexus/cache";
     const cache = new TagCache({ ttlMs: 60_000, staleWhileRevalidateMs: 300_000 });
     export default responseCache({ cache, tags: ["products"] });
    @@ -235,7 +235,7 @@ await bus.close();

    Pages }

    - + } } diff --git a/app/pages/packages/captcha.wrn b/app/pages/packages/captcha.wrn index 7046d6f4..6e0ddb85 100644 --- a/app/pages/packages/captcha.wrn +++ b/app/pages/packages/captcha.wrn @@ -10,11 +10,11 @@ page wrnexuscaptcha {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/captcha

    Managed CAPTCHA verification, middleware, and UI integration.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/captcha@0.8.4

    Request preview access. Never put registry tokens in source control.

    A first-class CAPTCHA and anti-automation package for WRNexusJS. It supports self-hosted challenges, a managed WRNexus service, external providers, form submission guards, page gates, accessible audio, adaptive risk checks, and a Tailwind-only .wrn component.

    +
    Security · Package reference

    @wrnexus/captcha

    Managed CAPTCHA verification, middleware, and UI integration.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/captcha@0.8.5

    Request preview access. Never put registry tokens in source control.

    A first-class CAPTCHA and anti-automation package for WRNexusJS. It supports self-hosted challenges, a managed WRNexus service, external providers, form submission guards, page gates, accessible audio, adaptive risk checks, and a Tailwind-only .wrn component.

    Install

    bun add @wrnexus/captcha

    WRNexusJS automatically discovers the package plugin, component, client runtime, styles, and DevToolbar audit. Use <Captcha /> directly after installation. The browser runtime is injected once only on responses that render a CAPTCHA; no script tag, public-file copy, or manual plugin registration is required. Call captchaPlugin(options) explicitly only when an application needs to override the discovered package configuration.

    @@ -333,7 +333,7 @@ export const HEAD = POST;
    - + } } diff --git a/app/pages/packages/cli.wrn b/app/pages/packages/cli.wrn index b3070bf2..ac1f70b1 100644 --- a/app/pages/packages/cli.wrn +++ b/app/pages/packages/cli.wrn @@ -10,11 +10,11 @@ page wrnexuscli {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/cli

    Create, develop, build, generate, test, and maintain WRNexusJS apps.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cli@0.8.4

    Request preview access. Never put registry tokens in source control.

    Production parity commands:

    +
    Tooling · Package reference

    @wrnexus/cli

    Create, develop, build, generate, test, and maintain WRNexusJS apps.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cli@0.8.5

    Request preview access. Never put registry tokens in source control.

    Production parity commands:

    wrnexus build .
     wrnexus preview . --port=3000
     wrnexus dev . --production-runtime
    @@ -167,7 +167,7 @@ wrnexus update --latest wrnexus doctor
    - + } } diff --git a/app/pages/packages/compiler.wrn b/app/pages/packages/compiler.wrn index bedb63d0..e86e85bb 100644 --- a/app/pages/packages/compiler.wrn +++ b/app/pages/packages/compiler.wrn @@ -10,11 +10,11 @@ page wrnexuscompiler {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/compiler

    Parser and code generators for the .wrn language.

    v0.8.4Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/compiler@0.8.4

    Request preview access. Never put registry tokens in source control.

    Partial-static rendering

    +
    Core · Package reference

    @wrnexus/compiler

    Parser and code generators for the .wrn language.

    v0.8.5Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/compiler@0.8.5

    Request preview access. Never put registry tokens in source control.

    Partial-static rendering

    Pages can select render = "partial-static" and divide their view with <Static> and <Dynamic> boundaries. The compiler emits a build-only shell renderer that never evaluates dynamic-boundary children. wrnexus build expands static component mounts into dist/partial-shells.json, records byte/region evidence in build-report.json, and embeds the shell in the production route manifest. At request time the production runtime retains request-aware layouts, locale/theme metadata and security nonces while streaming dynamic regions into stable placeholders.

    Compiler for the .wrn language — tokenizes, parses, and lowers .wrn page and component files to TypeScript.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    @@ -409,7 +409,7 @@ lx.next(); // { type: "ident", value: "Home", pos: 5 &# lx.next(); // { type: "lbrace", value: "{", pos: 10 }
    - + } } diff --git a/app/pages/packages/content.wrn b/app/pages/packages/content.wrn index a919d84a..fea17d91 100644 --- a/app/pages/packages/content.wrn +++ b/app/pages/packages/content.wrn @@ -10,11 +10,11 @@ page wrnexuscontent {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/content

    Content collections, validation, querying, and publishing workflows.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/content@0.8.4

    Request preview access. Never put registry tokens in source control.

    Typed content collections for Markdown/MDX-like documents and remote CMS records. Collections validate frontmatter through any { parse(input) } schema, render escaped HTML, and expose draft preview, versions, references, headings, search indexes, pagination, RSS and sitemaps.

    +
    Data · Package reference

    @wrnexus/content

    Content collections, validation, querying, and publishing workflows.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/content@0.8.5

    Request preview access. Never put registry tokens in source control.

    Typed content collections for Markdown/MDX-like documents and remote CMS records. Collections validate frontmatter through any { parse(input) } schema, render escaped HTML, and expose draft preview, versions, references, headings, search indexes, pagination, RSS and sitemaps.

    const posts = defineCollection({
       name: "posts",
       schema: PostSchema,
    @@ -170,7 +170,7 @@ const published = await posts.load();
     const preview = await posts.load({ previewToken: request.headers.get("x-preview-token") ?? "" });

    Install @wrnexus/content

    bun add @wrnexus/content
    - + } } diff --git a/app/pages/packages/core.wrn b/app/pages/packages/core.wrn index 22acd02d..1bbce856 100644 --- a/app/pages/packages/core.wrn +++ b/app/pages/packages/core.wrn @@ -10,11 +10,11 @@ page wrnexuscore {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/core

    Contexts, middleware, security, sessions, caching, JSX, and realtime.

    v0.8.4Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/core@0.8.4

    Request preview access. Never put registry tokens in source control.

    The framework core: the request Context, middleware contract, and the security, session, caching, streaming, realtime, and JSX primitives every other WRNexusJS package builds on.
    +
    Core · Package reference

    @wrnexus/core

    Contexts, middleware, security, sessions, caching, JSX, and realtime.

    v0.8.5Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/core@0.8.5

    Request preview access. Never put registry tokens in source control.

    The framework core: the request Context, middleware contract, and the security, session, caching, streaming, realtime, and JSX primitives every other WRNexusJS package builds on.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/core is the shared foundation of WRNexusJS. It defines the Context object that flows through every middleware, page, and API route, plus the Middleware/Next contract they implement. On top of that it ships the building blocks a real app needs: cookie-backed sessions, password auth, CSRF protection, rate limiting, request logging, HTTP + in-memory caching, file uploads, streaming/SSE responses, WebSocket "rooms", security headers/CORS, and a server-side JSX runtime that renders to HTML strings. Everything here is server-side and Bun-native (it uses Bun.password, Bun.write, the web-standard Request/Response, and crypto). You depend on it directly and transitively through the rest of the framework.

    @@ -1550,7 +1550,7 @@ const registry = createRealtimeRegistry(); bridgeRealtime(registry, createPubSub(redisDriver(process.env.REDIS_URL)));
    - + } } diff --git a/app/pages/packages/csr.wrn b/app/pages/packages/csr.wrn index 71b57f89..02b279bb 100644 --- a/app/pages/packages/csr.wrn +++ b/app/pages/packages/csr.wrn @@ -10,11 +10,11 @@ page wrnexuscsr {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/csr

    Reactive, navigation, and realtime browser runtimes.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/csr@0.8.4

    Request preview access. Never put registry tokens in source control.

    +
    Frontend · Package reference

    @wrnexus/csr

    Reactive, navigation, and realtime browser runtimes.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/csr@0.8.5

    Request preview access. Never put registry tokens in source control.

    Pages can opt into restoration across client navigation:

    page Users {
       navigation {
    @@ -330,7 +330,7 @@ room.on("chat", (msg) => console.log(msg.user, msg.text));
     room.send({ type: "chat", user: "ada", text: "hi" });
    - + } } diff --git a/app/pages/packages/db.wrn b/app/pages/packages/db.wrn index 376a20f8..53311f0d 100644 --- a/app/pages/packages/db.wrn +++ b/app/pages/packages/db.wrn @@ -10,11 +10,11 @@ page wrnexusdb {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/db

    Database adapters, typed queries, models, migrations, and sessions.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/db@0.8.4

    Request preview access. Never put registry tokens in source control.

    Rollout-safe migrations

    +
    Data · Package reference

    @wrnexus/db

    Database adapters, typed queries, models, migrations, and sessions.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/db@0.8.5

    Request preview access. Never put registry tokens in source control.

    Rollout-safe migrations

    Run wrnexus db check in CI before deployment. The analyzer reports stable diagnostics for drops, renames, type changes, new/enforced required columns, and potentially blocking index creation, with an expand/backfill/switch/contract recommendation. wrnexus db migrate blocks critical issues in pending migrations. --allow-breaking is an explicit operator override; already-applied migrations do not block later releases.

    The database layer for WRNexusJS: TS models as the single source of truth for DDL, validation, and result typing, plus a driver-based Db client, migrations, and a sqlc-style query generator.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    @@ -527,7 +527,7 @@ await repo.insert({ email: "a@b.com" }); const active = await repo.find({ active: true });
    - + } } diff --git a/app/pages/packages/dev-server.wrn b/app/pages/packages/dev-server.wrn index a17f654c..709fbcb1 100644 --- a/app/pages/packages/dev-server.wrn +++ b/app/pages/packages/dev-server.wrn @@ -10,11 +10,11 @@ page wrnexusdevserver {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/dev-server

    Development and production servers, HMR, assets, and gateways.

    v0.8.4Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-server@0.8.4

    Request preview access. Never put registry tokens in source control.

    The WRNexusJS HTTP + WebSocket server runtime — request dispatch, SSR document assembly, live-reload (HMR), and the portable production handler.
    +
    Runtime · Package reference

    @wrnexus/dev-server

    Development and production servers, HMR, assets, and gateways.

    v0.8.5Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-server@0.8.5

    Request preview access. Never put registry tokens in source control.

    The WRNexusJS HTTP + WebSocket server runtime — request dispatch, SSR document assembly, live-reload (HMR), and the portable production handler.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    This package is the server runtime that powers a WRNexusJS app in both development and production. A single request runtime (createHandlers) owns HTTP/WebSocket dispatch and SSR document assembly; it knows nothing about _how_ modules and assets are produced, so the dev and prod entry points wire in different backends: dev uses dynamic module loading plus on-the-fly bundling and injects a live-reload client; prod uses a static, pre-built manifest with cache-immutable assets. The package also ships a multi-app gateway (route several apps by Host header behind one port) and a portable node:http adapter for WinterCG hosts. It is entirely server-side and Bun-native (Bun.serve, Bun.file, Bun.gzipSync).

    @@ -237,6 +237,7 @@ import { DevToolbarConfig, DevToolbarPlatformSnapshot, DevToolbarPanel import { ClientRuntimeDefinition, PluginInput } from '@wrnexus/plugin'; import { CacheCoordinator } from '@wrnexus/cache'; import { DevToolbarCollector } from '@wrnexus/dev-toolbar/server'; +import { AuthzModule } from '@wrnexus/authz'; import { IncomingMessage, ServerResponse, Server } from 'node:http'; /** Exit code a dev-server child uses to request a clean supervisor restart. */ @@ -575,6 +576,11 @@ interface ProdManifest { name: string; mod: RouteModule; }[]; + /** RPC service implementations (from app/services/*.ts). */ + services?: { + name: string; + mod: RouteModule; + }[]; } interface ProductionPluginAsset { path: string; @@ -604,6 +610,19 @@ interface ProdOptions { frameworkCssPath?: string; /** Pre-built `window.__wireSchemas = {...}` script for client validation. */ schemasJs?: string; + /** + * Authorization declarations discovered by `wrnexus build` from + * `app/authz/*.ts`, statically imported into the generated entry (the + * catalog holds policy FUNCTIONS, so — unlike `schemasJs` — it cannot be + * JSON-serialised). `module` is `undefined` for a file with no default + * export. In the NORMAL generated-entry build, the catalog is already set + * by the generated `.authz-setup.ts` module before this ever runs (see + * `applyAuthzManifestEarly` below); `createProductionHandlers` merges this + * same list again as an idempotent second pass — with its warnings — so a + * caller that bypasses the generated entry and calls it directly still gets + * a correctly merged catalog. + */ + authz?: AuthzManifestEntry[]; /** Resolved i18n bundle (default lang + locale messages). */ i18n?: ResolvedI18n; /** Default database connection (driver + url); enables `getDb()`. */ @@ -668,6 +687,28 @@ interface ProdOptions { /** Enable only for the CLI's supervised exact-production development mode. */ developmentRuntime?: boolean; } +/** One `app/authz/*.ts` declaration as passed through `ProdOptions.authz`. */ +interface AuthzManifestEntry { + source: string; + /** Undefined when the declaration file has no default export. */ + module?: AuthzModule; +} +/** + * Merge + `setAuthzCatalog` as EARLY as possible, deliberately silently (no + * missing-default-export warnings). Called ONLY from the generated + * `.authz-setup.ts` module that `wrnexus build` imports FIRST in the + * production entry — before any other static import, including app + * middleware — so that a middleware module reading `getAuthzCatalog()` at its + * own module scope (the same eager shape `authzMiddleware({ catalog, ... })` + * itself requires) sees a populated catalog. `createProductionHandlers` below + * performs the exact same merge again, WITH its warnings, as the canonical, + * always-warns second pass — this function stays silent specifically so the + * normal boot path does not print the same "no default export" warning + * twice. A genuine conflict still throws here (via `mergeCatalogs`), which + * fails the boot at import time — before the entry body, and thus + * `createProductionHandlers`, ever runs. + */ +declare function applyAuthzManifestEarly(entries: AuthzManifestEntry[]): void; /** * Build the portable request handler from a precompiled manifest — a * WinterCG-style `fetch(request) => Response` plus the websocket handlers, with @@ -778,7 +819,7 @@ interface RunningServer { } declare function startServer(opts: ServeOptions): Promise<RunningServer>; -export { type AssetServer, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WrnCompileMetrics, type WsData, createHandlers, createProductionHandlers, createProductionServer, expandStaticComponents, getWrnCompileMetrics, nodeListener, precomputePartialStaticShell, resetWrnCompileMetrics, serveNode, startGateway, startServer, toRequest, writeResponse }; +export { type AssetServer, type AuthzManifestEntry, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WrnCompileMetrics, type WsData, applyAuthzManifestEarly, createHandlers, createProductionHandlers, createProductionServer, expandStaticComponents, getWrnCompileMetrics, nodeListener, precomputePartialStaticShell, resetWrnCompileMetrics, serveNode, startGateway, startServer, toRequest, writeResponse };

    Examples

    Copy-ready examples from the installed package documentation.

    Programmatic dev server

    import { startServer } from "@wrnexus/dev-server";
     
     const server = await startServer({
    @@ -819,7 +860,7 @@ await startGateway({
     });
    - + } } diff --git a/app/pages/packages/dev-toolbar.wrn b/app/pages/packages/dev-toolbar.wrn index 6febd994..4359885d 100644 --- a/app/pages/packages/dev-toolbar.wrn +++ b/app/pages/packages/dev-toolbar.wrn @@ -10,11 +10,11 @@ page wrnexusdevtoolbar {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/dev-toolbar

    Development toolbar diagnostics, inspection, and runtime status.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-toolbar@0.8.4

    Request preview access. Never put registry tokens in source control.

    Development-only page quality toolbar for WRNexusJS.

    +
    Tooling · Package reference

    @wrnexus/dev-toolbar

    Development toolbar diagnostics, inspection, and runtime status.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-toolbar@0.8.5

    Request preview access. Never put registry tokens in source control.

    Development-only page quality toolbar for WRNexusJS.

    Features

    • Runtime, resource and unhandled promise error capture
    • @@ -41,7 +41,7 @@ export { DEV_TOOLBAR_CSS, DEV_TOOLBAR_RUNTIME } from './client/index.j const issues = runDevToolbarRules(context);
    - + } } diff --git a/app/pages/packages/encryption.wrn b/app/pages/packages/encryption.wrn index 044c8bc3..6ae39956 100644 --- a/app/pages/packages/encryption.wrn +++ b/app/pages/packages/encryption.wrn @@ -10,11 +10,11 @@ page wrnexusencryption {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/encryption

    Hashing, HMAC, authenticated encryption, and key derivation.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/encryption@0.8.4

    Request preview access. Never put registry tokens in source control.

    Authenticated encryption, hashing, HMAC, key rotation, and optional encrypted HTTP exchanges for WRNexusJS.

    +
    Security · Package reference

    @wrnexus/encryption

    Hashing, HMAC, authenticated encryption, and key derivation.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/encryption@0.8.5

    Request preview access. Never put registry tokens in source control.

    Authenticated encryption, hashing, HMAC, key rotation, and optional encrypted HTTP exchanges for WRNexusJS.

    Core helpers

    • generateKey() — random 256-bit AES key encoded as base64.
    • @@ -213,7 +213,7 @@ const response = await fetch(request); const result = await decryptEncryptedResponse(response, request, { keyring });

    Install @wrnexus/encryption

    bun add @wrnexus/encryption
    - + } } diff --git a/app/pages/packages/graphql.wrn b/app/pages/packages/graphql.wrn index e8273f15..d13a9b33 100644 --- a/app/pages/packages/graphql.wrn +++ b/app/pages/packages/graphql.wrn @@ -10,16 +10,16 @@ page wrnexusgraphql {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/graphql

    GraphQL schemas, routes, and framework plugin integration.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/graphql@0.8.4

    Request preview access. Never put registry tokens in source control.

    Optional GraphQL endpoint plugin. Supply the executor from GraphQL.js, GraphQL Yoga, Mercurius, or another maintained engine; WRNexus owns bounded HTTP input, depth/alias limits, introspection policy, generic production errors and plugin route integration.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { G as GraphqlExecutionResult, a as GraphqlOptions, b as GraphqlRequest, c as createGraphqlHandler, default as graphqlPlugin } from './plugin.js';
    +      
    Data · Package reference

    @wrnexus/graphql

    GraphQL schemas, routes, and framework plugin integration.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/graphql@0.8.5

    Request preview access. Never put registry tokens in source control.

    Optional GraphQL endpoint plugin. Supply the executor from GraphQL.js, GraphQL Yoga, Mercurius, or another maintained engine; WRNexus owns bounded HTTP input, depth/alias limits, introspection policy, generic production errors and plugin route integration.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { G as GraphqlExecutionResult, a as GraphqlOptions, b as GraphqlRequest, c as createGraphqlHandler, default as graphqlPlugin } from './plugin.js';
     import '@wrnexus/plugin';
     

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/graphql

    bun add @wrnexus/graphql

    Import @wrnexus/graphql

    import * as graphql from "@wrnexus/graphql";
    - + } } diff --git a/app/pages/packages/helpers.wrn b/app/pages/packages/helpers.wrn index efbdea34..665af973 100644 --- a/app/pages/packages/helpers.wrn +++ b/app/pages/packages/helpers.wrn @@ -10,11 +10,11 @@ page wrnexushelpers {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/helpers

    Safe Context URL helpers and forward-auth login redirects.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/helpers@0.8.4

    Request preview access. Never put registry tokens in source control.

    Safe convenience helpers for common WRNexusJS application flows. The package uses standard Context, URL, and Response values and has no runtime dependency beyond @wrnexus/core.

    +
    Tooling · Package reference

    @wrnexus/helpers

    Safe Context URL helpers and forward-auth login redirects.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/helpers@0.8.5

    Request preview access. Never put registry tokens in source control.

    Safe convenience helpers for common WRNexusJS application flows. The package uses standard Context, URL, and Response values and has no runtime dependency beyond @wrnexus/core.

    bun add @wrnexus/helpers

    The package is private, so the machine must be authenticated to the wrnexus npm organization.

    Usage

    @@ -156,7 +156,7 @@ export const GET = async (ctx: Context) => { };
    - + } } diff --git a/app/pages/packages/i18n.wrn b/app/pages/packages/i18n.wrn index 44301f3a..50edd97a 100644 --- a/app/pages/packages/i18n.wrn +++ b/app/pages/packages/i18n.wrn @@ -10,11 +10,11 @@ page wrnexusi18n {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/i18n

    Translation loading, locale resolution, and Intl formatting.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/i18n@0.8.4

    Request preview access. Never put registry tokens in source control.

    Recursive locale loading, fallback resolution, SSR/browser translations, locale formatting, and language UI blocks for WRNexusJS.

    +
    Frontend · Package reference

    @wrnexus/i18n

    Translation loading, locale resolution, and Intl formatting.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/i18n@0.8.5

    Request preview access. Never put registry tokens in source control.

    Recursive locale loading, fallback resolution, SSR/browser translations, locale formatting, and language UI blocks for WRNexusJS.

    Locale files

    Both layouts can be used together:

    app/locales/en.json
    @@ -231,7 +231,7 @@ const enXA = createPseudoLocale(messages.en);
     const arXB = createPseudoLocale(messages.en, { rtl: true });
    - + } } diff --git a/app/pages/packages/identity.wrn b/app/pages/packages/identity.wrn index 12c216b4..96ac17e8 100644 --- a/app/pages/packages/identity.wrn +++ b/app/pages/packages/identity.wrn @@ -10,11 +10,11 @@ page wrnexusidentity {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/identity

    Portable identity records, claims, and account linking.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/identity@0.8.4

    Request preview access. Never put registry tokens in source control.

    Enterprise identity and governance for WRNexusJS: OIDC discovery, signed SAML adapter flows, LDAP/Active Directory synchronization adapters, SCIM provisioning, scoped API keys, service accounts, approval workflows, consent history, retention, subject export/deletion and audit.

    +
    Security · Package reference

    @wrnexus/identity

    Portable identity records, claims, and account linking.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/identity@0.8.5

    Request preview access. Never put registry tokens in source control.

    Enterprise identity and governance for WRNexusJS: OIDC discovery, signed SAML adapter flows, LDAP/Active Directory synchronization adapters, SCIM provisioning, scoped API keys, service accounts, approval workflows, consent history, retention, subject export/deletion and audit.

    The package complements @wrnexus/auth (passkeys, MFA, devices, sessions, OAuth and audited impersonation) and @wrnexus/authz (RBAC, ABAC and policy decisions). Protocol-specific SAML and directory parsing is supplied through adapters so applications can select a maintained vendor SDK without weakening framework validation, replay protection or governance auditing.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface OidcMetadata {
         issuer: string;
         authorization_endpoint: string;
    @@ -233,7 +233,7 @@ export { type DirectoryAdapter, type EnterpriseIdentity, type GovernanceEve
     

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/identity

    bun add @wrnexus/identity

    Import @wrnexus/identity

    import * as identity from "@wrnexus/identity";
    - + } } diff --git a/app/pages/packages/image.wrn b/app/pages/packages/image.wrn index 06c8f106..1749c97c 100644 --- a/app/pages/packages/image.wrn +++ b/app/pages/packages/image.wrn @@ -10,11 +10,11 @@ page wrnexusimage {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/image

    Responsive image optimization, loaders, placeholders, and components.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/image@0.8.4

    Request preview access. Never put registry tokens in source control.

    Secure responsive-image planning, loader adapters, picture sources, preload hints, placeholders, and performance auditing for WRNexusJS.

    +
    Frontend · Package reference

    @wrnexus/image

    Responsive image optimization, loaders, placeholders, and components.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/image@0.8.5

    Request preview access. Never put registry tokens in source control.

    Secure responsive-image planning, loader adapters, picture sources, preload hints, placeholders, and performance auditing for WRNexusJS.

    Build-time conversion is available through optimizeImage. It normalizes and bounds width/format variants, prevents variant explosions, writes deterministic filenames, and returns a manifest with dimensions and byte sizes:

    import { optimizeImage } from "@wrnexus/image";
     
    @@ -219,7 +219,7 @@ const picture = createPicture({
     });
    - + } } diff --git a/app/pages/packages/jwt.wrn b/app/pages/packages/jwt.wrn index 67b6b021..f2edea8e 100644 --- a/app/pages/packages/jwt.wrn +++ b/app/pages/packages/jwt.wrn @@ -10,11 +10,11 @@ page wrnexusjwt {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/jwt

    HS256 JWT signing, verification, and bearer authentication.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/jwt@0.8.4

    Request preview access. Never put registry tokens in source control.

    Dependency-free JSON Web Tokens (HS256) via Web Crypto, plus a bearer-token auth middleware for WRNexusJS.
    +
    Security · Package reference

    @wrnexus/jwt

    HS256 JWT signing, verification, and bearer authentication.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/jwt@0.8.5

    Request preview access. Never put registry tokens in source control.

    Dependency-free JSON Web Tokens (HS256) via Web Crypto, plus a bearer-token auth middleware for WRNexusJS.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/jwt signs and verifies stateless JSON Web Tokens using the HS256 (HMAC-SHA-256) algorithm. It has no runtime dependencies — signing and verification are implemented directly on the standard Web Crypto API (crypto.subtle), which Bun provides natively. It runs server-side and pairs with the session-based auth in @wrnexus/core, giving you a stateless option for API and mobile clients. Reach for it when you need bearer-token auth rather than cookie sessions.

    @@ -316,7 +316,7 @@ app.use(jwtAuth({ secret: process.env.JWT_SECRET! })); app.use(jwtAuth({ secret: process.env.JWT_SECRET!, required: false }));
    - + } } diff --git a/app/pages/packages/language-server.wrn b/app/pages/packages/language-server.wrn index ecee47a0..b468d375 100644 --- a/app/pages/packages/language-server.wrn +++ b/app/pages/packages/language-server.wrn @@ -10,11 +10,11 @@ page wrnexuslanguageserver {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/language-server

    Editor-neutral language intelligence for WRN files.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/language-server@0.8.4

    Request preview access. Never put registry tokens in source control.

    Editor-neutral Language Server Protocol support for .wrn files. It uses the canonical @wrnexus/syntax parser, diagnostics, accessibility rules, and formatter.

    +
    Tooling · Package reference

    @wrnexus/language-server

    Editor-neutral language intelligence for WRN files.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/language-server@0.8.5

    Request preview access. Never put registry tokens in source control.

    Editor-neutral Language Server Protocol support for .wrn files. It uses the canonical @wrnexus/syntax parser, diagnostics, accessibility rules, and formatter.

    bunx wrnexus-language-server --stdio

    Capabilities include syntax, accessibility and TypeScript expression diagnostics, formatting, completion, hover, document symbols, go-to-definition, references, rename, and quick fixes. The custom wrnexus/virtualDocument request returns the mapped TypeScript representation of an open .wrn document for editor TypeScript plugins and safe refactoring tools. Any LSP 3.x client can launch the stdio command. Example Neovim configuration:

    vim.lsp.start({
    @@ -157,7 +157,7 @@ export { type Position, type Range, type TextDocument, WRN_COMPLETIONS, typ
     })
    - + } } diff --git a/app/pages/packages/mcp.wrn b/app/pages/packages/mcp.wrn index 2ac1d23d..a280d511 100644 --- a/app/pages/packages/mcp.wrn +++ b/app/pages/packages/mcp.wrn @@ -10,11 +10,11 @@ page wrnexusmcp {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/mcp

    Model Context Protocol tools for WRNexus projects.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mcp@0.8.4

    Request preview access. Never put registry tokens in source control.

    Editor-neutral Model Context Protocol server for AI development tools.

    +
    Tooling · Package reference

    @wrnexus/mcp

    Model Context Protocol tools for WRNexus projects.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mcp@0.8.5

    Request preview access. Never put registry tokens in source control.

    Editor-neutral Model Context Protocol server for AI development tools.

    bunx wrnexus-mcp --root=.

    It exposes current routes, components with props/events, database schema files, compiler diagnostics, runtime errors, dev-server health, framework documentation and installed packages. Files are resolved inside the configured application root and returned as bounded structured JSON.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface McpTool {
         name: string;
    @@ -43,7 +43,7 @@ export { type McpServer, type McpServerOptions, type McpTool, createFramewo
     

    Examples

    Copy-ready examples from the installed package documentation.

    Editor-neutral Model Context Protocol server for AI development tools.

    bunx wrnexus-mcp --root=.

    Install @wrnexus/mcp

    bun add @wrnexus/mcp
    - + } } diff --git a/app/pages/packages/mobile.wrn b/app/pages/packages/mobile.wrn index 5873c111..f38b7fb1 100644 --- a/app/pages/packages/mobile.wrn +++ b/app/pages/packages/mobile.wrn @@ -10,11 +10,11 @@ page wrnexusmobile {
    W WRNexusJS - +
    -
    Native · Package reference

    @wrnexus/mobile

    SSR-safe compatibility access to Capacitor plugins.

    v0.8.4Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mobile@0.8.4

    Request preview access. Never put registry tokens in source control.

    SSR-safe access to Capacitor plugins from WRNexusJS browser code.
    +
    Native · Package reference

    @wrnexus/mobile

    SSR-safe compatibility access to Capacitor plugins.

    v0.8.5Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mobile@0.8.5

    Request preview access. Never put registry tokens in source control.

    SSR-safe access to Capacitor plugins from WRNexusJS browser code.

    Overview

    @wrnexus/mobile keeps optional native imports out of server rendering while giving browser-owned modules one consistent registry for Capacitor plugins. During SSR, mobile.isNative() is false and mobile.platform() is "web".

    Install a plugin through the WRNexusJS CLI so the web and native projects stay aligned:

    @@ -213,7 +213,7 @@ const network = mobile.plugin<NetworkPlugin>("Network"); const status = network ? await network.getStatus() : { connected: true, connectionType: "unknown" };
    - + } } diff --git a/app/pages/packages/native.wrn b/app/pages/packages/native.wrn index fb1a0847..5fba8fed 100644 --- a/app/pages/packages/native.wrn +++ b/app/pages/packages/native.wrn @@ -10,11 +10,11 @@ page wrnexusnative {
    W WRNexusJS - +
    -
    Native · Package reference

    @wrnexus/native

    Cross-platform browser and Capacitor capability registry.

    v0.8.4Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/native@0.8.4

    Request preview access. Never put registry tokens in source control.

    Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.
    +
    Native · Package reference

    @wrnexus/native

    Cross-platform browser and Capacitor capability registry.

    v0.8.5Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/native@0.8.5

    Request preview access. Never put registry tokens in source control.

    Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.

    Overview

    @wrnexus/native exposes capabilities by name so application code can ask what the current platform supports before presenting an action. Browser capabilities use Web APIs; mobile capabilities use installed Capacitor plugins. platform() returns "server" during SSR, "browser" on the web, and the Capacitor platform in a native WebView.

    bun add @wrnexus/native
    @@ -154,7 +154,7 @@ const position = await native.run( );
    - + } } diff --git a/app/pages/packages/oauth.wrn b/app/pages/packages/oauth.wrn index a24b92b1..54088b6b 100644 --- a/app/pages/packages/oauth.wrn +++ b/app/pages/packages/oauth.wrn @@ -10,11 +10,11 @@ page wrnexusoauth {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/oauth

    OAuth 2.0, PKCE, provider presets, and profile mapping.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/oauth@0.8.4

    Request preview access. Never put registry tokens in source control.

    Dependency-free OAuth 2.0 sign-in for any provider, with PKCE and presets for Google, GitHub, and Discord.
    +
    Security · Package reference

    @wrnexus/oauth

    OAuth 2.0, PKCE, provider presets, and profile mapping.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/oauth@0.8.5

    Request preview access. Never put registry tokens in source control.

    Dependency-free OAuth 2.0 sign-in for any provider, with PKCE and presets for Google, GitHub, and Discord.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/oauth implements the OAuth 2.0 Authorization Code flow (with PKCE) for server-side sign-in. It ships ready-made provider presets and a defineProvider helper for custom providers, then gives you two flow functions — startAuth (build the redirect) and completeAuth (exchange the code and fetch the user's profile). It has no runtime dependencies: it uses the platform fetch and WebCrypto only. Pairs naturally with @wrnexus/core's logIn to establish a session once you have a normalized profile.

    @@ -350,7 +350,7 @@ const gitlab = defineProvider({ });
    - + } } diff --git a/app/pages/packages/observability.wrn b/app/pages/packages/observability.wrn index 4756ebc2..c40b545c 100644 --- a/app/pages/packages/observability.wrn +++ b/app/pages/packages/observability.wrn @@ -10,11 +10,11 @@ page wrnexusobservability {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/observability

    Structured logging, tracing, health, and integration adapters.

    v0.8.4Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/observability@0.8.4

    Request preview access. Never put registry tokens in source control.

    Open-standard traces, metrics, logs, health checks, Web Vitals, error reporting and profiling.

    +
    Runtime · Package reference

    @wrnexus/observability

    Structured logging, tracing, health, and integration adapters.

    v0.8.5Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/observability@0.8.5

    Request preview access. Never put registry tokens in source control.

    Open-standard traces, metrics, logs, health checks, Web Vitals, error reporting and profiling.

    Use createOperationTracer() for database, cache, queue, realtime, server-action or custom application spans. Export through OTLP, Prometheus, Zipkin/Jaeger, or the Sentry-compatible error reporter; Grafana can consume the Prometheus or OTLP signals.

    Privacy-conscious counters, gauges, histograms, HTTP middleware, Web Vitals ingestion, browser collection, and exporter adapters. Request bodies and user identifiers are not collected by default.

    export default {
    @@ -126,7 +126,7 @@ export const live = createLivenessHandler();
     export const ready = createReadinessHandler(health);
    - + } } diff --git a/app/pages/packages/playground.wrn b/app/pages/packages/playground.wrn index 8c645e4d..f758ab12 100644 --- a/app/pages/packages/playground.wrn +++ b/app/pages/packages/playground.wrn @@ -10,11 +10,11 @@ page wrnexusplayground {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/playground

    Interactive framework examples and executable playground utilities.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/playground@0.8.4

    Request preview access. Never put registry tokens in source control.

    A deployable, shareable .wrn playground with diagnostics, generated JavaScript, safe SSR-shaped HTML, sandboxed preview, reactive/UI examples, and version adapters.

    +
    Tooling · Package reference

    @wrnexus/playground

    Interactive framework examples and executable playground utilities.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/playground@0.8.5

    Request preview access. Never put registry tokens in source control.

    A deployable, shareable .wrn playground with diagnostics, generated JavaScript, safe SSR-shaped HTML, sandboxed preview, reactive/UI examples, and version adapters.

    Run wrnexus playground, or deploy createPlaygroundHandler().

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface PlaygroundCompilation {
         source: string;
         generated: string;
    @@ -59,7 +59,7 @@ export { type PlaygroundCompilation, type PlaygroundVersionAdapter, compare
     

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/playground

    bun add @wrnexus/playground

    Import @wrnexus/playground

    import * as playground from "@wrnexus/playground";
    - + } } diff --git a/app/pages/packages/plugin.wrn b/app/pages/packages/plugin.wrn index 4ab7ff30..f0e960e3 100644 --- a/app/pages/packages/plugin.wrn +++ b/app/pages/packages/plugin.wrn @@ -10,11 +10,11 @@ page wrnexusplugin {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/plugin

    Plugin contracts, lifecycle hooks, composition, and framework integration.

    v0.8.4Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/plugin@0.8.4

    Request preview access. Never put registry tokens in source control.

    Least-privilege package permissions

    +
    Core · Package reference

    @wrnexus/plugin

    Plugin contracts, lifecycle hooks, composition, and framework integration.

    v0.8.5Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/plugin@0.8.5

    Request preview access. Never put registry tokens in source control.

    Least-privilege package permissions

    Package manifests declare every framework capability they register:

    {
       "wrnexus": {
    @@ -79,7 +79,7 @@ export { type PluginCompatibilityResult, type PluginCompatibilityTarget, Pl
     };
    - + } } diff --git a/app/pages/packages/pubsub.wrn b/app/pages/packages/pubsub.wrn index cc59338b..4ffd6473 100644 --- a/app/pages/packages/pubsub.wrn +++ b/app/pages/packages/pubsub.wrn @@ -10,11 +10,11 @@ page wrnexuspubsub {
    W WRNexusJS - +
    -
    Realtime · Package reference

    @wrnexus/pubsub

    In-process and Redis-backed publish/subscribe.

    v0.8.4Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pubsub@0.8.4

    Request preview access. Never put registry tokens in source control.

    Topic-based publish/subscribe with a pluggable driver — in-process by default, Redis for cross-process messaging.
    +
    Realtime · Package reference

    @wrnexus/pubsub

    In-process and Redis-backed publish/subscribe.

    v0.8.5Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pubsub@0.8.5

    Request preview access. Never put registry tokens in source control.

    Topic-based publish/subscribe with a pluggable driver — in-process by default, Redis for cross-process messaging.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/pubsub is a small server-side pub/sub bus. You publish messages to a topic and subscribe with topic patterns; handlers fire for matching topics. The default driver keeps everything in-process, and you can swap in the Redis driver (@wrnexus/pubsub/redis) to fan messages out across processes or hosts. It also backs @wrnexus/core's realtime bridge for horizontal scaling.

    @@ -197,7 +197,7 @@ await bus.publish("order:created", { id: 7 }); await bus.close();
    - + } } diff --git a/app/pages/packages/pwa.wrn b/app/pages/packages/pwa.wrn index 5c5300e8..0a46bd13 100644 --- a/app/pages/packages/pwa.wrn +++ b/app/pages/packages/pwa.wrn @@ -10,11 +10,11 @@ page wrnexuspwa {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/pwa

    Progressive Web App manifests, service workers, and offline strategies.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pwa@0.8.4

    Request preview access. Never put registry tokens in source control.

    Official PWA primitives for manifests, service workers, offline pages and precaching, runtime caching, background synchronization, push notifications, install/update events, offline mutation stores, and conflict resolution. createOfflineQueue() accepts a durable IndexedDB-style store and retries requests with stable idempotency headers.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface IndexedDbMigration {
    +      
    Frontend · Package reference

    @wrnexus/pwa

    Progressive Web App manifests, service workers, and offline strategies.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pwa@0.8.5

    Request preview access. Never put registry tokens in source control.

    Official PWA primitives for manifests, service workers, offline pages and precaching, runtime caching, background synchronization, push notifications, install/update events, offline mutation stores, and conflict resolution. createOfflineQueue() accepts a durable IndexedDB-style store and retries requests with stable idempotency headers.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface IndexedDbMigration {
         version: number;
         migrate(db: IDBDatabase, transaction: IDBTransaction): void;
     }
    @@ -176,7 +176,7 @@ export { type ConflictResolution, type IndexedDbMigration, type OfflineMuta
     

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/pwa

    bun add @wrnexus/pwa

    Import @wrnexus/pwa

    import * as pwa from "@wrnexus/pwa";
    - + } } diff --git a/app/pages/packages/queue.wrn b/app/pages/packages/queue.wrn index 831ceb85..ccc39529 100644 --- a/app/pages/packages/queue.wrn +++ b/app/pages/packages/queue.wrn @@ -10,11 +10,11 @@ page wrnexusqueue {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/queue

    Background jobs with delay, concurrency, retry, and repetition.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/queue@0.8.4

    Request preview access. Never put registry tokens in source control.

    A background job queue with delays, retries + exponential backoff, recurring jobs, and concurrent workers.
    +
    Data · Package reference

    @wrnexus/queue

    Background jobs with delay, concurrency, retry, and repetition.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/queue@0.8.5

    Request preview access. Never put registry tokens in source control.

    A background job queue with delays, retries + exponential backoff, recurring jobs, and concurrent workers.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/queue is a server-side in-process job queue. You register named workers, enqueue jobs (optionally delayed or recurring), and let the queue poll and run them on a timer — with per-job retry limits and doubling backoff between attempts. The default store lives in memory; the design allows a pluggable driver to back it with Redis/SQL for durability across restarts. Reach for it when you need to defer work (emails, webhooks, cleanup) off the request path without a heavyweight external broker. Tests can drive it deterministically via drain().

    @@ -421,7 +421,7 @@ const run = await engine.start(workflow, input); await engine.approve(workflow, run.id, "approve", currentUser.id);
    - + } } diff --git a/app/pages/packages/reactive.wrn b/app/pages/packages/reactive.wrn index 9b26f1b2..2ae1bef2 100644 --- a/app/pages/packages/reactive.wrn +++ b/app/pages/packages/reactive.wrn @@ -10,11 +10,11 @@ page wrnexusreactive {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/reactive

    Small type-safe reactive signal primitives.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/reactive@0.8.4

    Request preview access. Never put registry tokens in source control.

    Tiny, type-safe reactive primitives (signals) with zero dependencies.
    +
    Frontend · Package reference

    @wrnexus/reactive

    Small type-safe reactive signal primitives.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/reactive@0.8.5

    Request preview access. Never put registry tokens in source control.

    Tiny, type-safe reactive primitives (signals) with zero dependencies.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/reactive is the seed of WRNexusJS's reactivity layer: a minimal signal primitive that holds a value, notifies subscribers when it changes, and hands back an unsubscribe function. It is deliberately small and framework-agnostic — it powers nothing on its own, but is shaped so client islands (and later the .wrn compiler's state blocks) can build reactive bindings on top of it. Reach for it when you need observable state without pulling in a full reactivity library.

    @@ -206,7 +206,7 @@ const user: Signal<{ name: string } | null> = signal(null); user.set({ name: "Ada" });
    - + } } diff --git a/app/pages/packages/realtime.wrn b/app/pages/packages/realtime.wrn index e316685a..b26807c4 100644 --- a/app/pages/packages/realtime.wrn +++ b/app/pages/packages/realtime.wrn @@ -10,11 +10,11 @@ page wrnexusrealtime {
    W WRNexusJS - +
    -
    Realtime · Package reference

    @wrnexus/realtime

    Rooms, presence, messaging, history, streams, and UI components.

    v0.8.4Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/realtime@0.8.4

    Request preview access. Never put registry tokens in source control.

    Typed rooms, secure message envelopes, browser room helpers, presence utilities, and complete realtime UI blocks for WRNexusJS.

    +
    Realtime · Package reference

    @wrnexus/realtime

    Rooms, presence, messaging, history, streams, and UI components.

    v0.8.5Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/realtime@0.8.5

    Request preview access. Never put registry tokens in source control.

    Typed rooms, secure message envelopes, browser room helpers, presence utilities, and complete realtime UI blocks for WRNexusJS.

    Server rooms

    import { defineRoom } from "@wrnexus/realtime";
     
    @@ -267,7 +267,7 @@ history.acknowledge("support", clientId, entry.sequence);
     const missed = history.resume("support", clientId);
    - + } } diff --git a/app/pages/packages/router.wrn b/app/pages/packages/router.wrn index be218ece..575d74da 100644 --- a/app/pages/packages/router.wrn +++ b/app/pages/packages/router.wrn @@ -10,11 +10,11 @@ page wrnexusrouter {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/router

    Filesystem discovery, route matching, and typed route generation.

    v0.8.4Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/router@0.8.4

    Request preview access. Never put registry tokens in source control.

    File-based router that maps an app/ directory onto route tables and matches request paths against them.
    +
    Core · Package reference

    @wrnexus/router

    Filesystem discovery, route matching, and typed route generation.

    v0.8.5Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/router@0.8.5

    Request preview access. Never put registry tokens in source control.

    File-based router that maps an app/ directory onto route tables and matches request paths against them.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/router scans an application's app/ directory once at startup and builds route tables for pages, API endpoints, realtime channels, middleware, server-rendered .wrn components, layouts, and validation schemas. It also compiles URL patterns (/users/[id]) into RegExps and matches request paths against them. Request input is never turned into a file path, which makes the router immune to path traversal. This is a server-side package used by the WRNexusJS runtime to resolve incoming requests, plus a codegen helper for compile-time typed links.

    @@ -240,6 +240,10 @@ interface Router { stores: ComponentRef[]; /** Validation schemas (`app/schemas/<name>.ts`) shared by API + forms. */ schemas: ComponentRef[]; + /** Authorization declarations (`app/authz/<name>.ts`) merged into the catalog. */ + authz: ComponentRef[]; + /** Service implementations (`app/services/<name>.ts`) mounted for inter-app calls. */ + services: ComponentRef[]; matchPage(pathname: string): RouteMatch | null; matchApi(pathname: string): RouteMatch | null; matchRealtime(pathname: string): RouteMatch | null; @@ -302,7 +306,7 @@ const routes = sortRoutes([{ raw: "/posts/[slug]", file: " const m = matchRoute(routes, "/posts/hello"); // { route, params: { slug: "hello" } }
    - + } } diff --git a/app/pages/packages/security.wrn b/app/pages/packages/security.wrn index 29d672af..104704cc 100644 --- a/app/pages/packages/security.wrn +++ b/app/pages/packages/security.wrn @@ -10,16 +10,16 @@ page wrnexussecurity {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/security

    Security headers, CSRF protection, rate limits, and safe rendering.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/security@0.8.4

    Request preview access. Never put registry tokens in source control.

    Secure-by-default utilities for WRNexusJS: bounded HTML-safe serialization, prototype-pollution rejection, URL policy, secure cookies, request hardening, security presets, and SSRF-safe remote fetches.

    +
    Security · Package reference

    @wrnexus/security

    Security headers, CSRF protection, rate limits, and safe rendering.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/security@0.8.5

    Request preview access. Never put registry tokens in source control.

    Secure-by-default utilities for WRNexusJS: bounded HTML-safe serialization, prototype-pollution rejection, URL policy, secure cookies, request hardening, security presets, and SSRF-safe remote fetches.

    import { safeFetch, securityPreset, setSecureCookie } from "@wrnexus/security";
     
     export default { security: securityPreset("strict") };
     const response = await safeFetch(remoteUrl, { allowedHosts: ["api.example.com"] });
    -setSecureCookie(ctx, "__Host-session", sessionId);

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { S as SafeFetchOptions, a as SafeUrlPolicy, i as isPrivateAddress, b as isSafeUrl, s as safeFetch, c as sanitizeUrl, v as validateUrl } from './fetch-DNyX0J_D.js';
    +setSecureCookie(ctx, "__Host-session", sessionId);

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { S as SafeFetchOptions, a as SafeUrlPolicy, i as isPrivateAddress, b as isSafeUrl, s as safeFetch, c as sanitizeUrl, v as validateUrl } from './fetch-DzQ8J9S2.js';
     export { SecureSerializeOptions, secureJsonStringify, serializeForHtml } from './serialization.js';
     import { CookieOptions, Context, RequestLimitsConfig, Middleware, SecurityConfig } from '@wrnexus/core';
     export { TrustedHtmlPolicy, TrustedHtmlValue, createTrustedHtml, isTrustedHtml, unwrapTrustedHtml } from './trusted-html.js';
    @@ -59,7 +59,7 @@ const response = await safeFetch(remoteUrl, { allowedHosts: ["api.exam
     setSecureCookie(ctx, "__Host-session", sessionId);

    Install @wrnexus/security

    bun add @wrnexus/security
    - + } } diff --git a/app/pages/packages/ssr.wrn b/app/pages/packages/ssr.wrn index 9df919d4..e26fe9b5 100644 --- a/app/pages/packages/ssr.wrn +++ b/app/pages/packages/ssr.wrn @@ -10,11 +10,11 @@ page wrnexusssr {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/ssr

    Secure HTML document rendering and SEO metadata.

    v0.8.4Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ssr@0.8.4

    Request preview access. Never put registry tokens in source control.

    Server-side rendering: wraps a page's HTML body in a complete HTML document with a metadata-driven <head>.
    +
    Runtime · Package reference

    @wrnexus/ssr

    Secure HTML document rendering and SEO metadata.

    v0.8.5Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ssr@0.8.5

    Request preview access. Never put registry tokens in source control.

    Server-side rendering: wraps a page's HTML body in a complete HTML document with a metadata-driven <head>.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    Pages in WRNexusJS return an HTML string for the body. @wrnexus/ssr takes that body and produces a full HTML document — building the <head> from page metadata and global SEO defaults, resolving canonical/Open Graph/Twitter tags, and injecting module preloads and <script type="module"> tags. It is deliberately server-only: nothing in this package touches the DOM or ships to the browser, keeping server code genuinely server-only. Reach for it on the server when turning a rendered page body into a response document.

    @@ -224,7 +224,7 @@ return new Response(html, { return new Response(html, { headers: { "content-type": "text/html; charset=utf-8" } });
    - + } } diff --git a/app/pages/packages/store.wrn b/app/pages/packages/store.wrn index 42087e22..8df3028d 100644 --- a/app/pages/packages/store.wrn +++ b/app/pages/packages/store.wrn @@ -10,11 +10,11 @@ page wrnexusstore {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/store

    Application state stores shared across server and browser runtimes.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/store@0.8.4

    Request preview access. Never put registry tokens in source control.

    Typed global and page-scoped WRNexusJS stores with runtime-specific state, computed values, actions, lifecycle hooks, persistence, SSR isolation, and HMR support.

    +
    Data · Package reference

    @wrnexus/store

    Application state stores shared across server and browser runtimes.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/store@0.8.5

    Request preview access. Never put registry tokens in source control.

    Typed global and page-scoped WRNexusJS stores with runtime-specific state, computed values, actions, lifecycle hooks, persistence, SSR isolation, and HMR support.

    Use defineStore() to declare a store and createStoreContainer() to create an isolated request or browser container. Store definitions are framework helpers and do not require UI components.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { StoreMutation, StoreFunction, StoreDefinition, StoreInstance, StoreCombinedState } from './types.js';
     export { PersistenceStorage, StoreActionContext, StoreActionDefinition, StoreInstanceCore, StoreKind, StoreLifecycleContext, StorePersistenceConfig, StoreRuntime } from './types.js';
     
    @@ -62,7 +62,7 @@ export { StoreCombinedState, StoreContainer, type StoreContainerOptions, St
     

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/store

    bun add @wrnexus/store

    Import @wrnexus/store

    import * as store from "@wrnexus/store";
    - + } } diff --git a/app/pages/packages/styles.wrn b/app/pages/packages/styles.wrn index 0de79f8c..3fb5bfe8 100644 --- a/app/pages/packages/styles.wrn +++ b/app/pages/packages/styles.wrn @@ -10,11 +10,11 @@ page wrnexusstyles {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/styles

    CSS pipeline, themes, fonts, profiles, and application config.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/styles@0.8.4

    Request preview access. Never put registry tokens in source control.

    Reusable layers and presets

    +
    Frontend · Package reference

    @wrnexus/styles

    CSS pipeline, themes, fonts, profiles, and application config.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/styles@0.8.5

    Request preview access. Never put registry tokens in source control.

    Reusable layers and presets

    Compose local or package foundations in order; later layers override earlier ones and the application has final base-config precedence:

    export default defineConfig({
       extends: ["@workroot/wrnexus-enterprise", "./layers/company"],
    @@ -885,7 +885,7 @@ const themeJs = renderThemeRuntime(theme); // served at THEME_JS_HREF
    - + } } diff --git a/app/pages/packages/syntax.wrn b/app/pages/packages/syntax.wrn index 15610382..b6fb812d 100644 --- a/app/pages/packages/syntax.wrn +++ b/app/pages/packages/syntax.wrn @@ -10,11 +10,11 @@ page wrnexussyntax {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/syntax

    Editor syntax definitions and language tooling for .wrn files.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/syntax@0.8.4

    Request preview access. Never put registry tokens in source control.

    Canonical WRN lexer, parser, AST, language metadata, source positions, and stable diagnostics. Framework tooling should import this package instead of implementing a separate .wrn parser.

    +
    Frontend · Package reference

    @wrnexus/syntax

    Editor syntax definitions and language tooling for .wrn files.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/syntax@0.8.5

    Request preview access. Never put registry tokens in source control.

    Canonical WRN lexer, parser, AST, language metadata, source positions, and stable diagnostics. Framework tooling should import this package instead of implementing a separate .wrn parser.

    See docs/WRN-LANGUAGE-SPEC-1.0.md in the WRNexusJS repository.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { LexError, Lexer } from './tokenizer.js';
     export { FormatWrnOptions, formatWrn } from './formatter.js';
     export { A as ActionBlock, a as ApiBlock, b as Attr, C as ComputedDecl, D as DataApiBlock, c as DataMode, E as EffectBlock, d as EventDecl, F as FunctionParameterDecl, e as FunctionRuntime, L as LifecycleBlock, f as LoadBlock, M as ModeFunctionsBlock, O as OutputDecl, P as PageAst, g as ParseError, h as PersistDecl, i as PropDecl, R as RealtimeBlock, j as RealtimeHandler, k as RuntimeFunctionDecl, S as SeoBlock, l as StateDecl, m as StateRuntime, n as StoreKind, o as StoreLifecycleDecl, p as StructuredImportDecl, V as VOID_ELEMENTS, q as ViewNode, W as WatchBlock, r as parse, s as parseComputedDeclarations, t as parseHtmlView, u as parseOutputs, v as parsePersist, w as parseRuntimeFunctions, x as parseStateDeclarations, y as parseStoreLifecycle, z as parseStructuredImports, B as stripRuntimeFunctionModifiers } from './parser-CTLO4mcT.js';
    @@ -49,7 +49,7 @@ const ast = parse('component Greeting { view { <p>Hello</p>
     const summary = diagnosticSummary(diagnose(source));
    - + } } diff --git a/app/pages/packages/test.wrn b/app/pages/packages/test.wrn index bda846be..e2f5cddc 100644 --- a/app/pages/packages/test.wrn +++ b/app/pages/packages/test.wrn @@ -10,11 +10,11 @@ page wrnexustest {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/test

    WRNexusJS-aware component, route, and browser testing utilities.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/test@0.8.4

    Request preview access. Never put registry tokens in source control.

    Testing utilities for WRNexusJS apps — component rendering, reactive-DOM mounting, route handler calls, and a full in-process app harness, plus a one-import re-export of bun:test.
    +
    Tooling · Package reference

    @wrnexus/test

    WRNexusJS-aware component, route, and browser testing utilities.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/test@0.8.5

    Request preview access. Never put registry tokens in source control.

    Testing utilities for WRNexusJS apps — component rendering, reactive-DOM mounting, route handler calls, and a full in-process app harness, plus a one-import re-export of bun:test.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/test is the server-side test toolkit you reach for when writing tests for a WRNexusJS app. It runs under bun test (invoked via wrnexus test) and gives you a single import surface: the bun:test primitives (test, expect, mock, …) re-exported alongside WRNexusJS-aware helpers that compile .wrn components, hydrate server HTML in a DOM, invoke API route handlers, and boot the real app on an ephemeral port for integration tests.

    @@ -267,7 +267,7 @@ test("health endpoint", async () => { });
    - + } } diff --git a/app/pages/packages/tracking.wrn b/app/pages/packages/tracking.wrn index e66cef65..d677a682 100644 --- a/app/pages/packages/tracking.wrn +++ b/app/pages/packages/tracking.wrn @@ -10,11 +10,11 @@ page wrnexustracking {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/tracking

    Error/event capture, middleware, filtering, and sinks.

    v0.8.4Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/tracking@0.8.4

    Request preview access. Never put registry tokens in source control.

    Error tracking for WRNexusJS apps: capture exceptions manually or via middleware and fan them out to pluggable sinks.
    +
    Runtime · Package reference

    @wrnexus/tracking

    Error/event capture, middleware, filtering, and sinks.

    v0.8.5Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/tracking@0.8.5

    Request preview access. Never put registry tokens in source control.

    Error tracking for WRNexusJS apps: capture exceptions manually or via middleware and fan them out to pluggable sinks.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/tracking is a small, server-side error-capture layer. You create a tracker with one or more sinks, then feed it errors — either manually with tracker.capture(err, context) or automatically by mounting tracker.middleware() in your request pipeline. A consoleSink is included; forwarding to Sentry, Datadog, or any other backend is just a matter of writing a tiny sink. Reach for it when you want a single, sink-agnostic place to route application errors. Sinks run best-effort — a throwing sink never breaks the request.

    @@ -199,7 +199,7 @@ const tracker = createTracker({ tracker.addSink(anotherSink); // add more sinks later
    - + } } diff --git a/app/pages/packages/typecheck.wrn b/app/pages/packages/typecheck.wrn index f8299a02..f96b25be 100644 --- a/app/pages/packages/typecheck.wrn +++ b/app/pages/packages/typecheck.wrn @@ -10,11 +10,11 @@ page wrnexustypecheck {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/typecheck

    WRN-aware TypeScript diagnostics and virtual documents.

    v0.8.4Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/typecheck@0.8.4

    Request preview access. Never put registry tokens in source control.

    Static type checking for .wrn declarations, props, state, outputs, functions, stores, and generated virtual TypeScript files.

    +
    Tooling · Package reference

    @wrnexus/typecheck

    WRN-aware TypeScript diagnostics and virtual documents.

    v0.8.5Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/typecheck@0.8.5

    Request preview access. Never put registry tokens in source control.

    Static type checking for .wrn declarations, props, state, outputs, functions, stores, and generated virtual TypeScript files.

    The package is compiler tooling rather than a browser UI package, so its public kit consists of programmatic typecheck helpers and diagnostics.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { PageAst } from '@wrnexus/syntax';
     export { componentContract, storeContract } from './contracts.js';
     export { findAppRoot, loadApplicationTypes } from './project.js';
    @@ -65,7 +65,7 @@ export { type TypecheckOptions, type VirtualTypeScriptModule, type WrnTypeD
     

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/typecheck

    bun add @wrnexus/typecheck

    Import @wrnexus/typecheck

    import * as typecheck from "@wrnexus/typecheck";
    - + } } diff --git a/app/pages/packages/ui.wrn b/app/pages/packages/ui.wrn index e99e78b7..61bc7de4 100644 --- a/app/pages/packages/ui.wrn +++ b/app/pages/packages/ui.wrn @@ -10,11 +10,11 @@ page wrnexusui {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/ui

    Themeable server-rendered UI components and CSS.

    v0.8.4Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ui@0.8.4

    Request preview access. Never put registry tokens in source control.

    First-party Wire UI component library — a set of themeable .wrn components plus a single tokenized stylesheet.
    +
    Frontend · Package reference

    @wrnexus/ui

    Themeable server-rendered UI components and CSS.

    v0.8.5Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ui@0.8.5

    Request preview access. Never put registry tokens in source control.

    First-party Wire UI component library — a set of themeable .wrn components plus a single tokenized stylesheet.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/ui ships a library of server-rendered .wrn components (layout, form controls, and feedback UI) together with one themeable stylesheet, ui.css. The components are auto-discovered by the framework router — you don't import them in code. Once the package's component directory is on the router's scan path, you mount any component in a page with data-component="<name>". Every visual is driven by var(--wire-*) theme tokens, so components restyle instantly when the theme changes. The tiny JS surface (src/index.ts) exists only so the toolchain (CLI build + dev server) can locate the component directory and stylesheet.

    @@ -96,55 +96,8 @@ const router = buildRouter(appDir, { componentDirs: [uiComponentsDir()] 
  • Depends on [@wrnexus/core](../core) (dependencies).
  • theme-toggle relies on the framework's theme runtime, which binds the
  • data-wire-theme-toggle attribute — no per-component JS is required.

    -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface UiComponentMetadata {
    -    name: string;
    -    mount: string;
    -    category?: string;
    -    purpose?: string;
    -    props?: Array<{
    -        name: string;
    -        default?: unknown;
    -    }>;
    -    events?: string[];
    -}
    -interface UiComponentReference {
    -    count: number;
    -    components: UiComponentMetadata[];
    -}
    -declare function uiComponentReference(): UiComponentReference;
    -declare function findUiComponent(name: string): UiComponentMetadata | undefined;
    -declare function auditUiComponents(): Array<{
    -    component: string;
    -    issue: string;
    -}>;
    -
    -/**
    - * @wrnexus/ui — the Wire UI component library.
    - *
    - * Components are `.wrn` files under `components/`, auto-discovered by the
    - * framework (the router scans this directory in addition to the app's own
    - * `app/components`). Mount them in any page with `data-component="<name>"`.
    - * Their styles live in a single themeable stylesheet, `ui.css`, served once at
    - * `/__wrnexus/ui.css` — every class uses `var(--wire-*)` theme tokens.
    - *
    - * Override, in increasing order of power:
    - *   1. theme tokens (change `--wire-color-primary`, etc.)
    - *   2. redefine a `.wire-*` class in your own CSS (loaded after ui.css)
    - *   3. pass a `class` prop (appended to the component root)
    - *   4. `wrnexus eject <name>` to copy the component into `app/components` and own it
    - */
    -/** Absolute path to the directory of Wire UI component `.wrn` files. */
    -declare function uiComponentsDir(): string;
    -/** Absolute path to the Wire UI stylesheet. */
    -declare function uiCssPath(): string;
    -/** The Wire UI stylesheet contents (all `.wire-*` classes, themed via tokens). */
    -declare function uiCss(): string;
    -/** Names declared by the bundled components, independent of filename casing. */
    -declare function uiComponentNames(): string[];
    -/** Absolute path to a bundled component by its declared component name. */
    -declare function uiComponentPath(name: string): string;
    -
    -export { type UiComponentMetadata, type UiComponentReference, auditUiComponents, findUiComponent, uiComponentNames, uiComponentPath, uiComponentReference, uiComponentsDir, uiCss, uiCssPath };
    +

    Complete TypeScript API

    Generated from the exact installed package declarations.

    
    +export {  }
     

    Examples

    Copy-ready examples from the installed package documentation.

    Auto-discovery

    import { buildRouter } from "@wrnexus/router";
     import { uiComponentsDir } from "@wrnexus/ui";
     
    @@ -155,7 +108,7 @@ const router = buildRouter(appDir, { componentDirs: [uiComponentsDir()] 
     </div>

    Explore the component library

    Browse interactive examples and complete component usage in the dedicated WRNexusJS component showcase.

    Browse all 108 components →

    - + } } diff --git a/app/pages/packages/uploader.wrn b/app/pages/packages/uploader.wrn index 4418e1db..f51a84de 100644 --- a/app/pages/packages/uploader.wrn +++ b/app/pages/packages/uploader.wrn @@ -10,11 +10,11 @@ page wrnexusuploader {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/uploader

    Validated local/S3 uploads and secure file serving.

    v0.8.4Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/uploader@0.8.4

    Request preview access. Never put registry tokens in source control.

    Config-driven file uploads + serving for WRNexusJS. Declare named storage stores (local disk or any S3-compatible backend) in wrnexus.config.ts, upload with one function call, drop a drag-and-drop widget on a page, and serve files back — public or private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the rest of the framework).

    +
    Data · Package reference

    @wrnexus/uploader

    Validated local/S3 uploads and secure file serving.

    v0.8.5Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/uploader@0.8.5

    Request preview access. Never put registry tokens in source control.

    Config-driven file uploads + serving for WRNexusJS. Declare named storage stores (local disk or any S3-compatible backend) in wrnexus.config.ts, upload with one function call, drop a drag-and-drop widget on a page, and serve files back — public or private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the rest of the framework).

    Usage

    Configure local and S3 stores

    // wrnexus.config.ts
    @@ -632,7 +632,7 @@ import { serveFromStore } from "@wrnexus/uploader";
     export const GET = serveFromStore("docs"); // your middleware decides who gets in
    - + } } diff --git a/app/pages/packages/validation.wrn b/app/pages/packages/validation.wrn index 4d1274bd..acf42f66 100644 --- a/app/pages/packages/validation.wrn +++ b/app/pages/packages/validation.wrn @@ -10,11 +10,11 @@ page wrnexusvalidation {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/validation

    Typed schemas, coercion, validation, and browser descriptors.

    v0.8.4Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/validation@0.8.4

    Request preview access. Never put registry tokens in source control.

    One fluent schema, validated on the server (API bodies, env vars) and mirrored to an eval-free browser validator for forms.
    +
    Security · Package reference

    @wrnexus/validation

    Typed schemas, coercion, validation, and browser descriptors.

    v0.8.5Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/validation@0.8.5

    Request preview access. Never put registry tokens in source control.

    One fluent schema, validated on the server (API bodies, env vars) and mirrored to an eval-free browser validator for forms.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Boundary contracts

    Use ContractRegistry with defineContract or defineEvent to publish the same schema descriptors for APIs, actions, webhooks, realtime, queues, cron, pub/sub, plugins, configuration, and environment variables.

    @@ -545,7 +545,7 @@ const head = `<script>${renderSchemasScript({ signup: signupSche // render a <form data-schema="signup"> with [data-error="email"] etc.
    - + } } diff --git a/app/pages/releases/0.8.5.wrn b/app/pages/releases/0.8.5.wrn new file mode 100644 index 00000000..7e4ae32e --- /dev/null +++ b/app/pages/releases/0.8.5.wrn @@ -0,0 +1,16 @@ +page Release085 { + seo { + title = "Release 0.8.5" + description = "WRNexusJS 0.8.5 release notes." + canonical = "https://wrnexusjs.dev/releases/0.8.5" + } + view { + +
    +
    W WRNexusJS
    + +

    WRNexusJS 0.8.5

    Released 2026-07-13. All 47 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    + +
    + } +} \ No newline at end of file diff --git a/app/pages/roadmap.wrn b/app/pages/roadmap.wrn index 57dfe3a2..8a954c19 100644 --- a/app/pages/roadmap.wrn +++ b/app/pages/roadmap.wrn @@ -7,10 +7,10 @@ page Roadmap { view {
    -
    W WRNexusJS
    +
    W WRNexusJS

    Roadmap

    Roadmap items are direction, not delivery commitments. Dates require explicit owner approval.

    Now

    • Private preview onboarding and accurate package references
    • Runnable documentation fixtures and link/accessibility checks
    • License, support, and disclosure owner decisions

    Next

    • Durable queue driver guidance
    • Expanded database/auth/realtime examples
    • Versioned release notes and migration fixtures

    Later / exploration

    • Historical documentation selector
    • Maintained reproducible benchmarks
    • Broader mobile/native coverage
    - +
    } } \ No newline at end of file diff --git a/app/pages/search.wrn b/app/pages/search.wrn index c5ce3e08..750d5a6a 100644 --- a/app/pages/search.wrn +++ b/app/pages/search.wrn @@ -7,10 +7,10 @@ page Search { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -

    Search documentation

    This build-time index is local and sends no query to a third party. Use your browser’s find command to filter this compact index.

    Core documentation

    Get started · Packages · Components · Language · Architecture

    Guides

    Project structure · Routing · Pages and components · Server data · API routes · Middleware · Forms and validation · Authentication · Authorization · Application security · Database · Uploads · Realtime · Pub/sub · Queues · Testing · Workspaces and gateway · Deployment · Configuration and profiles · Internationalization and themes · Mobile · Observability · Upgrading · Troubleshooting

    Package APIs

    @wrnexus/ai · @wrnexus/authz · @wrnexus/compiler · @wrnexus/core · @wrnexus/csr · @wrnexus/db · @wrnexus/dev-server · @wrnexus/encryption · @wrnexus/helpers · @wrnexus/i18n · @wrnexus/jwt · @wrnexus/mobile · @wrnexus/native · @wrnexus/oauth · @wrnexus/pubsub · @wrnexus/queue · @wrnexus/reactive · @wrnexus/router · @wrnexus/ssr · @wrnexus/styles · @wrnexus/test · @wrnexus/tracking · @wrnexus/ui · @wrnexus/uploader · @wrnexus/validation · @wrnexus/dev-toolbar · @wrnexus/syntax · @wrnexus/plugin · @wrnexus/captcha · @wrnexus/auth · @wrnexus/store · @wrnexus/typecheck · @wrnexus/security · @wrnexus/cache · @wrnexus/image · @wrnexus/observability · @wrnexus/benchmark · @wrnexus/realtime · @wrnexus/content · @wrnexus/graphql · @wrnexus/identity · @wrnexus/language-server · @wrnexus/mcp · @wrnexus/playground · @wrnexus/pwa · @wrnexus/cli

    - +

    Search documentation

    This build-time index is local and sends no query to a third party. Use your browser’s find command to filter this compact index.

    Core documentation

    Get started · Packages · Components · Language · Architecture

    Guides

    Project structure · Routing · Pages and components · Server data · API routes · Middleware · Forms and validation · Authentication · Authorization · Application security · Database · Uploads · Realtime · Pub/sub · Queues · Testing · Workspaces and gateway · Deployment · Configuration and profiles · Internationalization and themes · Mobile · Observability · Upgrading · Troubleshooting

    Package APIs

    @wrnexus/ai · @wrnexus/authz · @wrnexus/compiler · @wrnexus/core · @wrnexus/csr · @wrnexus/db · @wrnexus/dev-server · @wrnexus/encryption · @wrnexus/helpers · @wrnexus/i18n · @wrnexus/jwt · @wrnexus/mobile · @wrnexus/native · @wrnexus/oauth · @wrnexus/pubsub · @wrnexus/queue · @wrnexus/reactive · @wrnexus/router · @wrnexus/ssr · @wrnexus/styles · @wrnexus/test · @wrnexus/tracking · @wrnexus/ui · @wrnexus/uploader · @wrnexus/validation · @wrnexus/dev-toolbar · @wrnexus/syntax · @wrnexus/plugin · @wrnexus/captcha · @wrnexus/auth · @wrnexus/store · @wrnexus/typecheck · @wrnexus/security · @wrnexus/cache · @wrnexus/image · @wrnexus/observability · @wrnexus/benchmark · @wrnexus/realtime · @wrnexus/content · @wrnexus/graphql · @wrnexus/identity · @wrnexus/language-server · @wrnexus/mcp · @wrnexus/playground · @wrnexus/pwa · @wrnexus/rpc · @wrnexus/cli

    +
    } } \ No newline at end of file diff --git a/app/pages/security.wrn b/app/pages/security.wrn index 79ddc967..1f27bb79 100644 --- a/app/pages/security.wrn +++ b/app/pages/security.wrn @@ -7,10 +7,10 @@ page Security { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -

    Security

    WRNexusJS provides primitives for CSP, CSRF, Trusted Types, sessions, validation, authorization, encryption, upload restrictions, request limits, and WebSocket-origin checks. Applications remain responsible for correct configuration, business authorization, secrets, dependencies, data protection, and operations.

    Supported releases

    Only the current private-preview release 0.8.4 is documented here. A formal old-release support window is not yet published.

    Report a vulnerability

    Use WorkRoot’s approved private contact path at workroot.in. Do not publish exploit details or secrets. Include affected version, impact, reproduction, and a safe contact method. Response targets, encryption key, bounty, audit, and certification are not currently claimed.

    Deployment controls

    Use restrictive CSP and permissions policies, HSTS only on HTTPS production origins, MIME sniffing protection, restrictive referrers, explicit CORS, secure cookies, CSRF validation, request limits, and origin checks. See application security.

    - +

    Security

    WRNexusJS provides primitives for CSP, CSRF, Trusted Types, sessions, validation, authorization, encryption, upload restrictions, request limits, and WebSocket-origin checks. Applications remain responsible for correct configuration, business authorization, secrets, dependencies, data protection, and operations.

    Supported releases

    Only the current private-preview release 0.8.5 is documented here. A formal old-release support window is not yet published.

    Report a vulnerability

    Use WorkRoot’s approved private contact path at workroot.in. Do not publish exploit details or secrets. Include affected version, impact, reproduction, and a safe contact method. Response targets, encryption key, bounty, audit, and certification are not currently claimed.

    Deployment controls

    Use restrictive CSP and permissions policies, HSTS only on HTTPS production origins, MIME sniffing protection, restrictive referrers, explicit CORS, secure cookies, CSRF validation, request limits, and origin checks. See application security.

    +
    } } \ No newline at end of file diff --git a/app/pages/showcase.wrn b/app/pages/showcase.wrn index 6216abcb..c33cc6e3 100644 --- a/app/pages/showcase.wrn +++ b/app/pages/showcase.wrn @@ -7,10 +7,10 @@ page Showcase { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -

    Showcase

    Only confirmed public properties are listed; no customer or traffic claims are made.

    WorkRoot

    Creator/company site demonstrating a public WRNexusJS deployment. Exact deployed version and infrastructure notes await owner confirmation.

    WRNexusJS docs

    This documentation portal, built and verified against WRNexusJS 0.8.4 on Bun.

    Screenshots are intentionally deferred until approved assets and alt text are available.

    - +

    Showcase

    Only confirmed public properties are listed; no customer or traffic claims are made.

    WorkRoot

    Creator/company site demonstrating a public WRNexusJS deployment. Exact deployed version and infrastructure notes await owner confirmation.

    WRNexusJS docs

    This documentation portal, built and verified against WRNexusJS 0.8.5 on Bun.

    Screenshots are intentionally deferred until approved assets and alt text are available.

    +
    } } \ No newline at end of file diff --git a/app/pages/support.wrn b/app/pages/support.wrn index 403310fe..492dae60 100644 --- a/app/pages/support.wrn +++ b/app/pages/support.wrn @@ -7,10 +7,10 @@ page Support { view {
    -
    W WRNexusJS
    +
    W WRNexusJS

    Support

    WRNexusJS has no public Discord, public issue tracker, or guaranteed community support channel listed by this repository. Preview access and support begin through WorkRoot’s public contact path.

    Include WRNexusJS version, Bun version, OS, a minimal reproduction, expected and actual behavior, and sanitized logs. Never include registry tokens, credentials, session cookies, or private data.

    Support scope, service levels, and commercial terms require owner confirmation.

    - +
    } } \ No newline at end of file diff --git a/app/pages/tutorial.wrn b/app/pages/tutorial.wrn index c9d74784..b2c898b1 100644 --- a/app/pages/tutorial.wrn +++ b/app/pages/tutorial.wrn @@ -7,9 +7,9 @@ page Tutorial { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -
    Preview · runnable-project extraction pending

    Secure task board

    This tutorial connects the installed 0.8.4 APIs into one design. Snippets are limited to declarations and README patterns verified in the installed packages; a CI-compiled standalone fixture remains on the roadmap.

    Application shape

    A .wrn page renders tasks from an SSR API binding. A shared validation schema protects mutations. Session middleware identifies users, authorization policies gate updates, and a realtime room broadcasts changes.

    Schema and create route

    import { v, parseBody } from "@wrnexus/validation";
    +      
    Preview · runnable-project extraction pending

    Secure task board

    This tutorial connects the installed 0.8.5 APIs into one design. Snippets are limited to declarations and README patterns verified in the installed packages; a CI-compiled standalone fixture remains on the roadmap.

    Application shape

    A .wrn page renders tasks from an SSR API binding. A shared validation schema protects mutations. Session middleware identifies users, authorization policies gate updates, and a realtime room broadcasts changes.

    Schema and create route

    import { v, parseBody } from "@wrnexus/validation";
     const task = v.object({ title: v.string().trim().min(3).max(120) });
     export const POST = async (ctx) => {
       const parsed = await parseBody(task, ctx.req);
    @@ -23,7 +23,7 @@ export const POST = async (ctx) => {
         </ul></main>
       }
     }

    Production checklist

    • Choose SQLite for local development or configure the supported PostgreSQL driver.
    • Run migrations before accepting traffic.
    • Enable session authentication and enforce authorization on every mutation.
    • Validate upload types and sizes; keep private objects behind authenticated routes.
    • Use Redis pub/sub when realtime rooms span processes.
    • Treat the default queue as non-durable until a production driver is selected.

    Follow the focused database, authentication, authorization, realtime, and upload guides.

    - +
    } } \ No newline at end of file diff --git a/app/routes.gen.ts b/app/routes.gen.ts index 760ce053..b8257508 100644 --- a/app/routes.gen.ts +++ b/app/routes.gen.ts @@ -168,6 +168,7 @@ export interface Routes { "/releases/0.8.2": Record; "/releases/0.8.3": Record; "/releases/0.8.4": Record; + "/releases/0.8.5": Record; "/roadmap": Record; "/search": Record; "/security": Record; @@ -343,6 +344,7 @@ export interface RouteNames { "releases.0.8.2": "/releases/0.8.2"; "releases.0.8.3": "/releases/0.8.3"; "releases.0.8.4": "/releases/0.8.4"; + "releases.0.8.5": "/releases/0.8.5"; "roadmap": "/roadmap"; "search": "/search"; "security": "/security"; @@ -587,6 +589,7 @@ export function route( "releases.0.8.2": "/releases/0.8.2", "releases.0.8.3": "/releases/0.8.3", "releases.0.8.4": "/releases/0.8.4", + "releases.0.8.5": "/releases/0.8.5", "roadmap": "/roadmap", "search": "/search", "security": "/security", diff --git a/app/types/wrnexus.generated.d.ts b/app/types/wrnexus.generated.d.ts index 3c47b85a..181b940b 100644 --- a/app/types/wrnexus.generated.d.ts +++ b/app/types/wrnexus.generated.d.ts @@ -14,7 +14,7 @@ declare namespace WRNexusGenerated { : never; type RealtimeMessage = T extends import("@wrnexus/core").RoomDefinition ? M : unknown; type QueuePayload = T extends import("@wrnexus/queue").JobDefinition ? I : unknown; - type RouteName = "404" | "access" | "architecture" | "benchmarks" | "changelog" | "examples" | "getting.started" | "guides.api.routes" | "guides.authentication" | "guides.authorization" | "guides.configuration.and.profiles" | "guides.database" | "guides.deployment" | "guides.forms.and.validation" | "guides.i18n.and.themes" | "guides.middleware" | "guides.mobile" | "guides.observability" | "guides.pages.and.components" | "guides.project.structure" | "guides.pubsub" | "guides.queues" | "guides.realtime" | "guides.routing" | "guides.security" | "guides.server.data" | "guides.testing" | "guides.troubleshooting" | "guides.upgrading" | "guides.uploads" | "guides.workspaces.and.gateway" | "index" | "language" | "license" | "packages" | "packages.ai" | "packages.auth" | "packages.authz" | "packages.benchmark" | "packages.cache" | "packages.captcha" | "packages.cli" | "packages.compiler" | "packages.content" | "packages.core" | "packages.csr" | "packages.db" | "packages.dev.server" | "packages.dev.toolbar" | "packages.encryption" | "packages.graphql" | "packages.helpers" | "packages.i18n" | "packages.identity" | "packages.image" | "packages.jwt" | "packages.language.server" | "packages.mcp" | "packages.mobile" | "packages.native" | "packages.oauth" | "packages.observability" | "packages.playground" | "packages.plugin" | "packages.pubsub" | "packages.pwa" | "packages.queue" | "packages.reactive" | "packages.realtime" | "packages.router" | "packages.security" | "packages.ssr" | "packages.store" | "packages.styles" | "packages.syntax" | "packages.test" | "packages.tracking" | "packages.typecheck" | "packages.ui" | "packages.uploader" | "packages.validation" | "releases.0.2.15" | "releases.0.2.17" | "releases.0.2.18" | "releases.0.2.19" | "releases.0.2.20" | "releases.0.2.21" | "releases.0.2.22" | "releases.0.2.23" | "releases.0.2.24" | "releases.0.2.25" | "releases.0.2.26" | "releases.0.2.27" | "releases.0.2.28" | "releases.0.2.29" | "releases.0.2.30" | "releases.0.2.31" | "releases.0.2.32" | "releases.0.2.33" | "releases.0.2.34" | "releases.0.2.35" | "releases.0.2.36" | "releases.0.2.37" | "releases.0.2.38" | "releases.0.2.39" | "releases.0.2.40" | "releases.0.2.41" | "releases.0.2.42" | "releases.0.2.43" | "releases.0.2.44" | "releases.0.2.45" | "releases.0.2.46" | "releases.0.2.47" | "releases.0.2.48" | "releases.0.2.49" | "releases.0.2.50" | "releases.0.2.51" | "releases.0.2.52" | "releases.0.2.53" | "releases.0.2.54" | "releases.0.2.55" | "releases.0.2.56" | "releases.0.2.57" | "releases.0.2.58" | "releases.0.2.59" | "releases.0.2.60" | "releases.0.2.61" | "releases.0.2.62" | "releases.0.2.63" | "releases.0.2.64" | "releases.0.2.65" | "releases.0.2.66" | "releases.0.2.67" | "releases.0.2.68" | "releases.0.2.69" | "releases.0.2.70" | "releases.0.2.71" | "releases.0.2.72" | "releases.0.2.73" | "releases.0.2.74" | "releases.0.2.75" | "releases.0.2.76" | "releases.0.2.77" | "releases.0.2.78" | "releases.0.2.79" | "releases.0.3.0" | "releases.0.3.1" | "releases.0.3.2" | "releases.0.3.3" | "releases.0.3.4" | "releases.0.3.5" | "releases.0.3.6" | "releases.0.4.0" | "releases.0.5.0" | "releases.0.5.1" | "releases.0.5.10" | "releases.0.5.11" | "releases.0.5.12" | "releases.0.5.13" | "releases.0.6.0" | "releases.0.7.0" | "releases.0.8.0" | "releases.0.8.1" | "releases.0.8.2" | "releases.0.8.3" | "releases.0.8.4" | "roadmap" | "search" | "security" | "showcase" | "support" | "tutorial"; + type RouteName = "404" | "access" | "architecture" | "benchmarks" | "changelog" | "examples" | "getting.started" | "guides.api.routes" | "guides.authentication" | "guides.authorization" | "guides.configuration.and.profiles" | "guides.database" | "guides.deployment" | "guides.forms.and.validation" | "guides.i18n.and.themes" | "guides.middleware" | "guides.mobile" | "guides.observability" | "guides.pages.and.components" | "guides.project.structure" | "guides.pubsub" | "guides.queues" | "guides.realtime" | "guides.routing" | "guides.security" | "guides.server.data" | "guides.testing" | "guides.troubleshooting" | "guides.upgrading" | "guides.uploads" | "guides.workspaces.and.gateway" | "index" | "language" | "license" | "packages" | "packages.ai" | "packages.auth" | "packages.authz" | "packages.benchmark" | "packages.cache" | "packages.captcha" | "packages.cli" | "packages.compiler" | "packages.content" | "packages.core" | "packages.csr" | "packages.db" | "packages.dev.server" | "packages.dev.toolbar" | "packages.encryption" | "packages.graphql" | "packages.helpers" | "packages.i18n" | "packages.identity" | "packages.image" | "packages.jwt" | "packages.language.server" | "packages.mcp" | "packages.mobile" | "packages.native" | "packages.oauth" | "packages.observability" | "packages.playground" | "packages.plugin" | "packages.pubsub" | "packages.pwa" | "packages.queue" | "packages.reactive" | "packages.realtime" | "packages.router" | "packages.security" | "packages.ssr" | "packages.store" | "packages.styles" | "packages.syntax" | "packages.test" | "packages.tracking" | "packages.typecheck" | "packages.ui" | "packages.uploader" | "packages.validation" | "releases.0.2.15" | "releases.0.2.17" | "releases.0.2.18" | "releases.0.2.19" | "releases.0.2.20" | "releases.0.2.21" | "releases.0.2.22" | "releases.0.2.23" | "releases.0.2.24" | "releases.0.2.25" | "releases.0.2.26" | "releases.0.2.27" | "releases.0.2.28" | "releases.0.2.29" | "releases.0.2.30" | "releases.0.2.31" | "releases.0.2.32" | "releases.0.2.33" | "releases.0.2.34" | "releases.0.2.35" | "releases.0.2.36" | "releases.0.2.37" | "releases.0.2.38" | "releases.0.2.39" | "releases.0.2.40" | "releases.0.2.41" | "releases.0.2.42" | "releases.0.2.43" | "releases.0.2.44" | "releases.0.2.45" | "releases.0.2.46" | "releases.0.2.47" | "releases.0.2.48" | "releases.0.2.49" | "releases.0.2.50" | "releases.0.2.51" | "releases.0.2.52" | "releases.0.2.53" | "releases.0.2.54" | "releases.0.2.55" | "releases.0.2.56" | "releases.0.2.57" | "releases.0.2.58" | "releases.0.2.59" | "releases.0.2.60" | "releases.0.2.61" | "releases.0.2.62" | "releases.0.2.63" | "releases.0.2.64" | "releases.0.2.65" | "releases.0.2.66" | "releases.0.2.67" | "releases.0.2.68" | "releases.0.2.69" | "releases.0.2.70" | "releases.0.2.71" | "releases.0.2.72" | "releases.0.2.73" | "releases.0.2.74" | "releases.0.2.75" | "releases.0.2.76" | "releases.0.2.77" | "releases.0.2.78" | "releases.0.2.79" | "releases.0.3.0" | "releases.0.3.1" | "releases.0.3.2" | "releases.0.3.3" | "releases.0.3.4" | "releases.0.3.5" | "releases.0.3.6" | "releases.0.4.0" | "releases.0.5.0" | "releases.0.5.1" | "releases.0.5.10" | "releases.0.5.11" | "releases.0.5.12" | "releases.0.5.13" | "releases.0.6.0" | "releases.0.7.0" | "releases.0.8.0" | "releases.0.8.1" | "releases.0.8.2" | "releases.0.8.3" | "releases.0.8.4" | "releases.0.8.5" | "roadmap" | "search" | "security" | "showcase" | "support" | "tutorial"; type ApiRoute = never; type RealtimeRoute = never; type EnvironmentKey = never; diff --git a/bun.lock b/bun.lock index 7237da27..41efebd9 100644 --- a/bun.lock +++ b/bun.lock @@ -7,58 +7,59 @@ "dependencies": { "@iconify-json/lucide": "^1.2.118", "@iconify/tailwind4": "^1.2.3", - "@wrnexus/ai": "^0.8.4", - "@wrnexus/auth": "^0.8.4", - "@wrnexus/authz": "^0.8.4", - "@wrnexus/benchmark": "^0.8.4", - "@wrnexus/cache": "^0.8.4", - "@wrnexus/captcha": "^0.8.4", - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/content": "^0.8.4", - "@wrnexus/core": "^0.8.4", - "@wrnexus/csr": "^0.8.4", - "@wrnexus/db": "^0.8.4", - "@wrnexus/dev-server": "^0.8.4", - "@wrnexus/dev-toolbar": "^0.8.4", - "@wrnexus/encryption": "^0.8.4", - "@wrnexus/graphql": "^0.8.4", - "@wrnexus/helpers": "^0.8.4", - "@wrnexus/i18n": "^0.8.4", - "@wrnexus/identity": "^0.8.4", - "@wrnexus/image": "^0.8.4", - "@wrnexus/jwt": "^0.8.4", - "@wrnexus/language-server": "^0.8.4", - "@wrnexus/mcp": "^0.8.4", - "@wrnexus/mobile": "^0.8.4", - "@wrnexus/native": "^0.8.4", - "@wrnexus/oauth": "^0.8.4", - "@wrnexus/observability": "^0.8.4", - "@wrnexus/playground": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/pubsub": "^0.8.4", - "@wrnexus/pwa": "^0.8.4", - "@wrnexus/queue": "^0.8.4", - "@wrnexus/reactive": "^0.8.4", - "@wrnexus/realtime": "^0.8.4", - "@wrnexus/router": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/ssr": "^0.8.4", - "@wrnexus/store": "^0.8.4", - "@wrnexus/styles": "^0.8.4", - "@wrnexus/syntax": "^0.8.4", - "@wrnexus/test": "^0.8.4", - "@wrnexus/tracking": "^0.8.4", - "@wrnexus/typecheck": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/uploader": "^0.8.4", - "@wrnexus/validation": "^0.8.4", + "@wrnexus/ai": "^0.8.5", + "@wrnexus/auth": "^0.8.5", + "@wrnexus/authz": "^0.8.5", + "@wrnexus/benchmark": "^0.8.5", + "@wrnexus/cache": "^0.8.5", + "@wrnexus/captcha": "^0.8.5", + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/content": "^0.8.5", + "@wrnexus/core": "^0.8.5", + "@wrnexus/csr": "^0.8.5", + "@wrnexus/db": "^0.8.5", + "@wrnexus/dev-server": "^0.8.5", + "@wrnexus/dev-toolbar": "^0.8.5", + "@wrnexus/encryption": "^0.8.5", + "@wrnexus/graphql": "^0.8.5", + "@wrnexus/helpers": "^0.8.5", + "@wrnexus/i18n": "^0.8.5", + "@wrnexus/identity": "^0.8.5", + "@wrnexus/image": "^0.8.5", + "@wrnexus/jwt": "^0.8.5", + "@wrnexus/language-server": "^0.8.5", + "@wrnexus/mcp": "^0.8.5", + "@wrnexus/mobile": "^0.8.5", + "@wrnexus/native": "^0.8.5", + "@wrnexus/oauth": "^0.8.5", + "@wrnexus/observability": "^0.8.5", + "@wrnexus/playground": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/pubsub": "^0.8.5", + "@wrnexus/pwa": "^0.8.5", + "@wrnexus/queue": "^0.8.5", + "@wrnexus/reactive": "^0.8.5", + "@wrnexus/realtime": "^0.8.5", + "@wrnexus/router": "^0.8.5", + "@wrnexus/rpc": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/ssr": "^0.8.5", + "@wrnexus/store": "^0.8.5", + "@wrnexus/styles": "^0.8.5", + "@wrnexus/syntax": "^0.8.5", + "@wrnexus/test": "^0.8.5", + "@wrnexus/tracking": "^0.8.5", + "@wrnexus/typecheck": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/uploader": "^0.8.5", + "@wrnexus/validation": "^0.8.5", }, "devDependencies": { "@eslint/js": "^9.0.0", "@tailwindcss/cli": "^4.0.0", "@types/bun": "latest", "@types/node": "^26.1.1", - "@wrnexus/cli": "^0.8.4", + "@wrnexus/cli": "^0.8.5", "eslint": "^9.0.0", "prettier": "latest", "tailwindcss": "^4.0.0", @@ -232,97 +233,99 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.63.0", "", { "dependencies": { "@typescript-eslint/types": "8.63.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw=="], - "@wrnexus/ai": ["@wrnexus/ai@0.8.4", "", {}, "sha512-iL391Ka6ompz7NcdfFtvEDOCqPKGz+VCJQN3xIbQERBJ131zpXxa9GQF3myR7w3gtiydLGnajiqbRgpbTG5VvQ=="], + "@wrnexus/ai": ["@wrnexus/ai@0.8.5", "", {}, "sha512-TLRbvepuMnIZmsmMH/5cTzHfdkvK2+lNU+CX/2DIRHAC8/ghz2wpp7ZVv/J6LU7shygJx/IDDOJfKlAAwFjEvA=="], - "@wrnexus/auth": ["@wrnexus/auth@0.8.4", "", { "dependencies": { "@wrnexus/authz": "^0.8.4", "@wrnexus/captcha": "^0.8.4", "@wrnexus/core": "^0.8.4", "@wrnexus/db": "^0.8.4", "@wrnexus/encryption": "^0.8.4", "@wrnexus/jwt": "^0.8.4", "@wrnexus/oauth": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/queue": "^0.8.4", "@wrnexus/ui": "^0.8.4", "@wrnexus/validation": "^0.8.4" } }, "sha512-N86/29UaDWWqC5O2bgylQzhp0rwH3+KdVxQ1oBr1tIP7DKsNo7ZrlDaMH9RSbVbzhdLwEl4G1+a4lrHBr7UM6g=="], + "@wrnexus/auth": ["@wrnexus/auth@0.8.5", "", { "dependencies": { "@wrnexus/authz": "^0.8.5", "@wrnexus/captcha": "^0.8.5", "@wrnexus/core": "^0.8.5", "@wrnexus/db": "^0.8.5", "@wrnexus/encryption": "^0.8.5", "@wrnexus/jwt": "^0.8.5", "@wrnexus/oauth": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/queue": "^0.8.5", "@wrnexus/ui": "^0.8.5", "@wrnexus/validation": "^0.8.5" } }, "sha512-6KbeRreKjew3LlY1u5t681nrzZzVMT19hFCRFVeAsL8Avc/VzYqd5G6QdcV2ixDObz4pIktXJL/Yg4LfvzQZ+w=="], - "@wrnexus/authz": ["@wrnexus/authz@0.8.4", "", {}, "sha512-oyQl6HtzsUPhw9yDENNRopF6n9tq+yPbZU5q97gvGaQ8n7AzzlW/y6f9uNEYGXjZZjcBopCAeqVireZGLDw+3Q=="], + "@wrnexus/authz": ["@wrnexus/authz@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/db": "^0.8.5" } }, "sha512-tgtnNkPp+qVk0W6Tq/Kn4PXsbD14mAEpGKhvNyHwqY/fU5zp3D+1L+RjiWPA2r0+qOhfePOJdgBFvbODAdBcrA=="], - "@wrnexus/benchmark": ["@wrnexus/benchmark@0.8.4", "", {}, "sha512-vck4FcNHggvIuGMdSxbu+NYedAtmVXGsbPNC8FpmhZ7lJviDAv1gqHf4YW33MA9x8yWdwQAHIygSy68pdPYbbA=="], + "@wrnexus/benchmark": ["@wrnexus/benchmark@0.8.5", "", {}, "sha512-PjtCCI7KUuKQW1k2K0apjVnvUIPocPmxOJii/TnsxgzNYE5W22IFux5rOK93sM2zUJVB6aUaR4jQhCxctUMjsg=="], - "@wrnexus/cache": ["@wrnexus/cache@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-twzmNRylE6PNu63xt2j9cNjKm+AhhcscVaXbPMbsWN7sKuL4O0kC/Iny0elD1jtXt3xAG4iayOzCiaxLhtEbUg=="], + "@wrnexus/cache": ["@wrnexus/cache@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-d3SXerkaUArgWo68FXdyr2owtji9cSHEsMH6bkQIAgFh3BvbQn5nvA+BHX37EqUAWpMcOMfSG9tw08kLFgBTHA=="], - "@wrnexus/captcha": ["@wrnexus/captcha@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/ui": "^0.8.4", "@wrnexus/validation": "^0.8.4" } }, "sha512-8KubI7v6NsfJRhJB+OgHNJSDsDgtLlWBLcxYBv+C0YE7QTdD96NNJ3X0m9e/aAYwGlKChLW/pc7iVQ4/Uv1vxQ=="], + "@wrnexus/captcha": ["@wrnexus/captcha@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/ui": "^0.8.5", "@wrnexus/validation": "^0.8.5" } }, "sha512-QFH+MXxiIZWEfZDUm28pJcCkDkRFb7Dehw4URscuMZar4wCrWCsE+xdhtHZiNiaBqwfSwWFqcH2qVjweT/ZVDg=="], - "@wrnexus/cli": ["@wrnexus/cli@0.8.4", "", { "dependencies": { "@wrnexus/compiler": "^0.8.4", "@wrnexus/core": "^0.8.4", "@wrnexus/csr": "^0.8.4", "@wrnexus/db": "^0.8.4", "@wrnexus/dev-server": "^0.8.4", "@wrnexus/i18n": "^0.8.4", "@wrnexus/mcp": "^0.8.4", "@wrnexus/playground": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/router": "^0.8.4", "@wrnexus/security": "^0.8.4", "@wrnexus/styles": "^0.8.4", "@wrnexus/syntax": "^0.8.4", "@wrnexus/typecheck": "^0.8.4", "@wrnexus/ui": "^0.8.4", "@wrnexus/validation": "^0.8.4", "selfsigned": "^5.5.0" }, "bin": { "wrnexus": "dist/index.js" } }, "sha512-1xnKsbWWKxIQaZD9sDBAzmSYsRU2+7vcq0IQotoHHKcRwV06myda4kcTQcFMpzELr9Um/to7gYIXC274f1k0Vw=="], + "@wrnexus/cli": ["@wrnexus/cli@0.8.5", "", { "dependencies": { "@wrnexus/authz": "^0.8.5", "@wrnexus/compiler": "^0.8.5", "@wrnexus/core": "^0.8.5", "@wrnexus/csr": "^0.8.5", "@wrnexus/db": "^0.8.5", "@wrnexus/dev-server": "^0.8.5", "@wrnexus/i18n": "^0.8.5", "@wrnexus/mcp": "^0.8.5", "@wrnexus/playground": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/router": "^0.8.5", "@wrnexus/security": "^0.8.5", "@wrnexus/styles": "^0.8.5", "@wrnexus/syntax": "^0.8.5", "@wrnexus/typecheck": "^0.8.5", "@wrnexus/ui": "^0.8.5", "@wrnexus/validation": "^0.8.5", "selfsigned": "^5.5.0" }, "bin": { "wrnexus": "dist/index.js" } }, "sha512-k0QOLnDrDY/gNzY3VTEZgYhobI3xJH0xjqjdVr2/6VBxkmuDXqZt1vOLS37p5ugbfpLOw+aIrcfQ8iG4u3w2iw=="], - "@wrnexus/compiler": ["@wrnexus/compiler@0.8.4", "", { "dependencies": { "@wrnexus/csr": "^0.8.4", "@wrnexus/store": "^0.8.4", "@wrnexus/syntax": "^0.8.4", "@wrnexus/validation": "^0.8.4" } }, "sha512-8t+rrBE1WVKUTUFSkktFGbEz2Hy62bwKvOs2/b9pTse9N3oqwlpg7NmGUue7N46x5jjDmOk8xSoKAzX3OG1QaQ=="], + "@wrnexus/compiler": ["@wrnexus/compiler@0.8.5", "", { "dependencies": { "@wrnexus/csr": "^0.8.5", "@wrnexus/store": "^0.8.5", "@wrnexus/syntax": "^0.8.5", "@wrnexus/validation": "^0.8.5" } }, "sha512-+jU7J8SBsDylMw22y5LiK1R80Etv5o5uX5bELGVxiKD/au2rw6JTFI7ERxVFjw4i4C1ASnwkfA6pnbUzbdP6Lw=="], - "@wrnexus/content": ["@wrnexus/content@0.8.4", "", {}, "sha512-1PUuUJeT/yOVC/OldUAqdQ2JH3SZiynuBK+Q2nlqir+W0mC6I4ezkG7paewIWh8N+FPXY3N485IlUrGMgAQi9A=="], + "@wrnexus/content": ["@wrnexus/content@0.8.5", "", {}, "sha512-pD7gqEY+phI4ggfQ7/SG927GgPSUkGDHk3mXSAFJmIQl2xoeVRlLSilbnYOaHT8+rR4Fx/zMuGNhu2SCOMk/Ag=="], - "@wrnexus/core": ["@wrnexus/core@0.8.4", "", {}, "sha512-7Vk7Xbjlw9sNbpljFAE2Np6CCyb09LJRKJqDmLsoc54wopS6RIPBfJXAbsezNdwh7EiTFsIyQ/KwojZUQf9hPA=="], + "@wrnexus/core": ["@wrnexus/core@0.8.5", "", {}, "sha512-mKPNgOKa68T1056Z/Ond1WL7qBT2pDvG72WQfdQ4Z8+XQ9aQXLr5tikBtoUOW5xj9mQdQLJ3Di4tqjhjCMoR1g=="], - "@wrnexus/csr": ["@wrnexus/csr@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-hTjZYET+SMNuc4B3tMUJXmmmapi6MdTN8V7PpfhCBsGnurP+oufR7r1ayWCakjt6y2PINp1/nUdO2Wz03H1V+A=="], + "@wrnexus/csr": ["@wrnexus/csr@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-e1kh6PyA9CnzVmbQRcvBPvkJzsIWP4Z6HDppFDOymwIKPf7/aFck2u7r5pM9XDLLuNaJOPyq2BOfj1a/vF1yUQ=="], - "@wrnexus/db": ["@wrnexus/db@0.8.4", "", {}, "sha512-y890w4Kpb+Ve7gMI+CCbgMtzXgxvHFiMtsY8ODBHxs7G0DVheUehmnfNxmajh4ufxO3co20j5h7lx9vyD3/+og=="], + "@wrnexus/db": ["@wrnexus/db@0.8.5", "", {}, "sha512-cRLPfh+4+0iOTrWW5HqMiHRyUdmQLMAdtSPeB9XkCSctUZFfRGjKRpqnlgzglh4q2TijFymSiJUpVCut84KpLA=="], - "@wrnexus/dev-server": ["@wrnexus/dev-server@0.8.4", "", { "dependencies": { "@wrnexus/cache": "^0.8.4", "@wrnexus/compiler": "^0.8.4", "@wrnexus/core": "^0.8.4", "@wrnexus/csr": "^0.8.4", "@wrnexus/db": "^0.8.4", "@wrnexus/dev-toolbar": "^0.8.4", "@wrnexus/i18n": "^0.8.4", "@wrnexus/observability": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/pubsub": "^0.8.4", "@wrnexus/pwa": "^0.8.4", "@wrnexus/router": "^0.8.4", "@wrnexus/security": "^0.8.4", "@wrnexus/ssr": "^0.8.4", "@wrnexus/store": "^0.8.4", "@wrnexus/styles": "^0.8.4", "@wrnexus/ui": "^0.8.4", "@wrnexus/uploader": "^0.8.4", "@wrnexus/validation": "^0.8.4" } }, "sha512-UKyLaIsZTEtPN3OgPxyV6LCirNXBOcGDY/vFL4egTInIYzWTMH0qxq/pKfm7CFztcQqBVRBlyO9/nCqeZet7FQ=="], + "@wrnexus/dev-server": ["@wrnexus/dev-server@0.8.5", "", { "dependencies": { "@wrnexus/authz": "^0.8.5", "@wrnexus/cache": "^0.8.5", "@wrnexus/compiler": "^0.8.5", "@wrnexus/core": "^0.8.5", "@wrnexus/csr": "^0.8.5", "@wrnexus/db": "^0.8.5", "@wrnexus/dev-toolbar": "^0.8.5", "@wrnexus/i18n": "^0.8.5", "@wrnexus/observability": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/pubsub": "^0.8.5", "@wrnexus/pwa": "^0.8.5", "@wrnexus/router": "^0.8.5", "@wrnexus/rpc": "^0.8.5", "@wrnexus/security": "^0.8.5", "@wrnexus/ssr": "^0.8.5", "@wrnexus/store": "^0.8.5", "@wrnexus/styles": "^0.8.5", "@wrnexus/ui": "^0.8.5", "@wrnexus/uploader": "^0.8.5", "@wrnexus/validation": "^0.8.5" } }, "sha512-kSztqn4b+eeJeAadT+fWxVCxG2jXGrrxWbzOBHTGzN2KI4Z8nHlvJZCY1XOpUUCsGwKfF6jC29n2L5N0DBjYNQ=="], - "@wrnexus/dev-toolbar": ["@wrnexus/dev-toolbar@0.8.4", "", {}, "sha512-dpXfAyZ+WL5aWrl0Gw1ddKIpxd8Wirq8hAbVFQ84fNSE27yyIUpr5tXIk15MstB9xv3W1o6Ufiotv8iGp7EwbQ=="], + "@wrnexus/dev-toolbar": ["@wrnexus/dev-toolbar@0.8.5", "", {}, "sha512-gIg/OQlAD63XRtQ0ncAu6RuDQaVTOYgBxUSgIB6dq4+LZQGsKgv7GZMej5LwGOJsw1eU1+X7qtUqJ8GWiWQNSw=="], - "@wrnexus/encryption": ["@wrnexus/encryption@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-3mB/3qBZdvJ2YaiTf6Gjs52uCIfzoxTS0sykvruAkslbKNKVW8iI3NYlZohoIVp6ZuqP86CnTZCxG/EhHi6N+Q=="], + "@wrnexus/encryption": ["@wrnexus/encryption@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-nfqb2DJ2FHGozkfxrxOeNrb96fZ4X5IJXM0DCF0Ix75nnHFcYEVc2MXll1uoQt0K6YYUl27NzVx2W7Sakz6hFA=="], - "@wrnexus/graphql": ["@wrnexus/graphql@0.8.4", "", { "dependencies": { "@wrnexus/plugin": "^0.8.4" } }, "sha512-rdlQ3t/X9XIGRs9CnUjZMSbop5X/IpzsRE36fRV0t2vpDGoUFPt9igvg05Hla09rPcnXQyrNtIxW4BjPdsqwwA=="], + "@wrnexus/graphql": ["@wrnexus/graphql@0.8.5", "", { "dependencies": { "@wrnexus/plugin": "^0.8.5" } }, "sha512-/9+ONokYh9b3ZiLT8XVz8BQNOTsPjYHx6TG74X4YpkG4wpIYB7T2aWzgheAeHg/qPy3l17gbQiMDnH9VzEU3/g=="], - "@wrnexus/helpers": ["@wrnexus/helpers@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-RkPVULBY9amUXo0S7UDWxXv9KnFbzj0rO8l3YNKR7CGGcUnl4C77gFMyjDez8mlavjZannpXaMdh4RMuT6bDxQ=="], + "@wrnexus/helpers": ["@wrnexus/helpers@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-2FHTuCklh4JKv3w0bfNW2qm/ulweSvluFF0GoIG7EVjBxP6AQO6JyaaZVddd/7N1k5Klnbir9+aiDBgcbf5gWQ=="], - "@wrnexus/i18n": ["@wrnexus/i18n@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/ui": "^0.8.4" } }, "sha512-wSbnxETNycQzbZy8V39B0ZsmZYez8qaEs5e6ODAR+k+3FY//G5CYQxARJxeQAQ7wL3qaLoEBmPxG3eySXnOCPg=="], + "@wrnexus/i18n": ["@wrnexus/i18n@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/ui": "^0.8.5" } }, "sha512-9VgDK6pjVk7QPG/WYtDmqLw2myBKTMHu5Bl39rX52yJY6bm6W9o+/bFZ14x3IlJ66JFO+XTkHviC2RnQwUD8TQ=="], - "@wrnexus/identity": ["@wrnexus/identity@0.8.4", "", { "dependencies": { "@wrnexus/auth": "^0.8.4", "@wrnexus/authz": "^0.8.4", "@wrnexus/oauth": "^0.8.4" } }, "sha512-uCI/4ThVSHvDIxQLJ669E9OtzMhi3+2JRjz6VHN5p3zuQbLOVDglMGOOuahLs3NrJTvOqy9fDtuTLVoKESTcDQ=="], + "@wrnexus/identity": ["@wrnexus/identity@0.8.5", "", { "dependencies": { "@wrnexus/auth": "^0.8.5", "@wrnexus/authz": "^0.8.5", "@wrnexus/oauth": "^0.8.5" } }, "sha512-YUQ/8XunmUFEyHbqOhITHV5KgszJGLCDvGZvlXkHUzbia5B2nakYy0Gw+RsSumYCGcXmxalbSx+UhmMkHY+cfA=="], - "@wrnexus/image": ["@wrnexus/image@0.8.4", "", { "dependencies": { "@wrnexus/plugin": "^0.8.4", "@wrnexus/security": "^0.8.4", "@wrnexus/ui": "^0.8.4" } }, "sha512-BRDLAD8hUqkdjxSe/OVrkZTSd6o000jN2Ai1A41St+PS9/fmcNZgg2nZXcK30T12wxYoFCDAn++WshF3mEdf2w=="], + "@wrnexus/image": ["@wrnexus/image@0.8.5", "", { "dependencies": { "@wrnexus/plugin": "^0.8.5", "@wrnexus/security": "^0.8.5", "@wrnexus/ui": "^0.8.5" } }, "sha512-+Bf3DNaLQAw4oMYCw3U9wT1h6AGQH1uC7PjKPNsns1pxhpqeSjOOjLI3pI8HaWjeR9D9sZ3XaGqqV3ly7LFZ1g=="], - "@wrnexus/jwt": ["@wrnexus/jwt@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-6QFRX7hBjLmmwMXggH1WOHop6fXQcqbP05YZPWDExLEC6MNBxaChs31ihSHkZczsxF5zmvPaLfrL80CpycXsFg=="], + "@wrnexus/jwt": ["@wrnexus/jwt@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-tj3UnWR1Uqtrnon4+UNlHcI1pqgmk/ul4b+Oc9HynKd1r7OqO41P92AFgFTPHyeR1xRrl0/ELaIqpE/uIz4wrw=="], - "@wrnexus/language-server": ["@wrnexus/language-server@0.8.4", "", { "dependencies": { "@wrnexus/syntax": "^0.8.4", "@wrnexus/typecheck": "^0.8.4" }, "bin": { "wrnexus-language-server": "dist/server.js" } }, "sha512-nk8no6MiPq5nFWbNiBIofU7GzTVW4viCr5K6ErxqyEbv2loQdPjV1YBR9z1D7EHbQlywMuJeV4OeIBiHxeuMew=="], + "@wrnexus/language-server": ["@wrnexus/language-server@0.8.5", "", { "dependencies": { "@wrnexus/syntax": "^0.8.5", "@wrnexus/typecheck": "^0.8.5" }, "bin": { "wrnexus-language-server": "dist/server.js" } }, "sha512-G2UmH+a9/9xxaJqqYeOHx/A1baj8TELCKy2ehoa/H1jB9ZbMl0GXkzUS0jZSHEDio6Ln2R1wpC6PvSIkwmAsWg=="], - "@wrnexus/mcp": ["@wrnexus/mcp@0.8.4", "", { "bin": { "wrnexus-mcp": "dist/stdio.js" } }, "sha512-1maJkJCCLLGggmO01eWIs2LgejBUxdR8aQO/HDuSuhI+vQvJrLlYBkqvjquVjr2Nlhv7ui7LBcLsVRAPBNw7Tw=="], + "@wrnexus/mcp": ["@wrnexus/mcp@0.8.5", "", { "bin": { "wrnexus-mcp": "dist/stdio.js" } }, "sha512-xDcXX9sYkBOX5CHYTEi7zjPr0SRReyN+p9zvLQFjVK0WVv9TRws9FckSujyz1RNHjSf0PxK2vr9d0ibdxG33Pw=="], - "@wrnexus/mobile": ["@wrnexus/mobile@0.8.4", "", { "dependencies": { "@wrnexus/native": "^0.8.4" } }, "sha512-/63nsfwF1vZ9bHgPTuyd7F9ej9DRzPJJFx/H+fm9iXOD+ew15gBmPLwt7GJJWoUu99Wi2aiFVzM1/KVyy7gNqA=="], + "@wrnexus/mobile": ["@wrnexus/mobile@0.8.5", "", { "dependencies": { "@wrnexus/native": "^0.8.5" } }, "sha512-qHbwKp3TIAdRBEaV/7ixDA4LUyArsJZmOCGlTsrA2xQiO3YGvMNNsh9rjSqZuQO5tC1WrJVXMmOnMbtJf2jJjQ=="], - "@wrnexus/native": ["@wrnexus/native@0.8.4", "", {}, "sha512-4llVTslb87a7qhAJUlFQ/PYbFrmsasKwOj9kgve02vo/IneiLJ4/QE1vGKVsUAgmdpt2picTwF/YyWssvQmBmg=="], + "@wrnexus/native": ["@wrnexus/native@0.8.5", "", {}, "sha512-181rt4/KLBcCOcRe62N0Txx6fiJplsmz4e8F6nbC2gGKplxH+WYXfp0+ZeL6szXqhVBb/rbsZgRi9Xots/7xHw=="], - "@wrnexus/oauth": ["@wrnexus/oauth@0.8.4", "", { "dependencies": { "@wrnexus/jwt": "^0.8.4" } }, "sha512-jl7T6KQkA96GLGJ3ZJCobaAiXsLvrcrH7d2VRIoITuHQtgJ3s/aC5BcfmqwokjT4guqEeC/K7CkD5bivbWvlPw=="], + "@wrnexus/oauth": ["@wrnexus/oauth@0.8.5", "", { "dependencies": { "@wrnexus/jwt": "^0.8.5" } }, "sha512-kkYXRaftZGcKnvm3UxlgUBnE6DWZ5/cTSj4LIJ3C4Y2j0vXdso+CSmPPzXM3TvPY/4d1NQMuBOB69JC83s70nA=="], - "@wrnexus/observability": ["@wrnexus/observability@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-VFji7+lNcZ0AXRHChw80rTwIYjkfyk4Cu9MvGp9uorNoWeYiI6ns4f6yhwIEtOG/5XwYIpytHNim5TPtOdzk3g=="], + "@wrnexus/observability": ["@wrnexus/observability@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-gEWx5mruRElJbCKTYRFdncotXHJOqw7Bzm41dcR+NVvkZlV8ome+s8f8XPzlJWpYmFYVzGj9N0ev14AP3ax9kw=="], - "@wrnexus/playground": ["@wrnexus/playground@0.8.4", "", { "dependencies": { "@wrnexus/compiler": "^0.8.4", "@wrnexus/syntax": "^0.8.4" } }, "sha512-Y/gx/VIKhAazUTSSQaN4Hr3akzeTjsFkUj03kqWHY5NQUNlk874hYDksdFVKjtMbj2I3npxq4ADLr2l9+HEc5w=="], + "@wrnexus/playground": ["@wrnexus/playground@0.8.5", "", { "dependencies": { "@wrnexus/compiler": "^0.8.5", "@wrnexus/syntax": "^0.8.5" } }, "sha512-8saMjmZfRiFXMlMa4qjyG66xfVqCoQhsW/KeIQUF/MkCFtm8FGkexgR5RANiH8wALD/d8uEMNnPMRg7B1iWymw=="], - "@wrnexus/plugin": ["@wrnexus/plugin@0.8.4", "", { "dependencies": { "@wrnexus/syntax": "^0.8.4" } }, "sha512-1EiZt0NvpC3pH75TVbWM4GCWF/lS+9jlsIV3IMX/1I/QoXaABtWuRnXgSh7ROmVe1fE3hd1EwYGlWN9vWim4XA=="], + "@wrnexus/plugin": ["@wrnexus/plugin@0.8.5", "", { "dependencies": { "@wrnexus/syntax": "^0.8.5" } }, "sha512-PYgpNZ6dmJvv+DJUtv8rKd1SAQ0as12Y5UZcy0SpHU+ZUrrrOakwpOtAdXlKJTG1+1rsZjbdDVgFIauSnnOOpg=="], - "@wrnexus/pubsub": ["@wrnexus/pubsub@0.8.4", "", {}, "sha512-6RVg5x8jLGO2HIv0kX5RTq7TI0A+Ki1VnbB86yCW3Kl3F5ABwe5SJwDxkzVhz9RPCHn08+TStYpNrWKd4Ofx+g=="], + "@wrnexus/pubsub": ["@wrnexus/pubsub@0.8.5", "", {}, "sha512-3XNKkRestcL8UDCM1GBWxbl6W5k1vx4Gi1XzpsWF9TrAf42wwFgYvdTrDknNqf58Mf7QGUAhwZFL/HN4AIH7/A=="], - "@wrnexus/pwa": ["@wrnexus/pwa@0.8.4", "", {}, "sha512-xWB8WjCxaY7qtVkzhk6I9kPX5ReUtUdgKdaSFiWHNg5moeUEk2cVLmzWcOSKNRUEZ2vVos93vyaFIlTctR5/DQ=="], + "@wrnexus/pwa": ["@wrnexus/pwa@0.8.5", "", {}, "sha512-mpXZqlD1M9OForvmdFPdjisZM+ymf7qpm2U7FvneogXxsUIrTSGUEtPg9QMKdw30WkTR4zqvEpCbfWaVOSkhIA=="], - "@wrnexus/queue": ["@wrnexus/queue@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-5osvXmVGnBuaLyboKzn5RPk/Vef/qpp0t83lAffoMDI7QkTD9rPBkStHvKiYqYB3tOXGE0x0o9LT1kuiorkuAQ=="], + "@wrnexus/queue": ["@wrnexus/queue@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-2IT0Gj+THkyqu+8X/XfHn4JEkhd/MvYMIGv5al7WFDgmrOb20Ls6dfNDenoDmXjSWkLcACRRXYTX+Zxj6/2MKQ=="], - "@wrnexus/reactive": ["@wrnexus/reactive@0.8.4", "", {}, "sha512-1G1DY39jfkuqTDh2XfQfh+5oCL1CNTwEnHw65SNrX4L6KrWKLWy+dEYxCZ6dJNUFYvP+9jsz9H5DsvspAutSCw=="], + "@wrnexus/reactive": ["@wrnexus/reactive@0.8.5", "", {}, "sha512-ccRzjvXz5PZDajFBJ4pclQ9AIFrFpn8ZAwgi+OSiQJSr6elDVdx+lDNQXngkfK2OuJyBvkZNg/7GLnT9sbm6eg=="], - "@wrnexus/realtime": ["@wrnexus/realtime@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/ui": "^0.8.4" } }, "sha512-F9gi6R9PV84k3uXTnWva2Y2NTUloLluG1GIibP2uuGNvii9Osp30+wYAWQKL2E8rDoGQTZWGWBwmEY9Yjj8tkA=="], + "@wrnexus/realtime": ["@wrnexus/realtime@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/ui": "^0.8.5" } }, "sha512-oGIF/RAmrlo2hrXRYNIwNDHNcdrUT0CYo5vXk3GDiXGTeDpIdoGxwP7qVYNYxTkqHvxJnA4Lls4MtZBD63nuqQ=="], - "@wrnexus/router": ["@wrnexus/router@0.8.4", "", { "dependencies": { "@wrnexus/compiler": "^0.8.4", "@wrnexus/core": "^0.8.4" } }, "sha512-qb3kNnsoUB447V4LD9Fh2BudklBvWCX/ksEYT6/jLAbtBA1wtNpCzi1mkYXod5mZZhGT6gjrXwXyBb7ZZ6MvLw=="], + "@wrnexus/router": ["@wrnexus/router@0.8.5", "", { "dependencies": { "@wrnexus/compiler": "^0.8.5", "@wrnexus/core": "^0.8.5" } }, "sha512-vKwKHNynHGufqD2xjntGzvf0ZwFrqWWnrs7H3gbIg9cUfbD6zdaYYDEm0UpuEDR4A5g6Y2hvEcPTyncj+nIQjw=="], - "@wrnexus/security": ["@wrnexus/security@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-UPOdf2w29ae80GPG1k6aQ4xvfxlwTG/+4ADPqfKmJzgTjRX+rKyzX80TOGPN9q3h2DBqEJjMCWN86gQAvPLiMA=="], + "@wrnexus/rpc": ["@wrnexus/rpc@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/helpers": "^0.8.5", "@wrnexus/jwt": "^0.8.5", "@wrnexus/validation": "^0.8.5" } }, "sha512-qxG/GayQxN9iusJ50M4ybsXPwdJUYCEB0Pkghs7dG1B+FcKOrYDkysx+zwaQ3uYN8ugfL4hk2NPmczRow41x3w=="], - "@wrnexus/ssr": ["@wrnexus/ssr@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/security": "^0.8.4", "@wrnexus/store": "^0.8.4" } }, "sha512-1JZjTwfTFMZAPA43TkPlgNI0qd1b8YJNIPtDzpTgdUA7PVK0umiIMffTFCv7wY1lLtGYckgblI3Dg+JOQgVpHg=="], + "@wrnexus/security": ["@wrnexus/security@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-JJ2kzLdlWv3BuixJIi4HwMEk6Ke+gLmvINVJf5JInxsqc+hpikGyPDdkgCsY/6uS0ZS4vnFOiHs7GgmLwPQ33g=="], - "@wrnexus/store": ["@wrnexus/store@0.8.4", "", {}, "sha512-etkNk/6nzuTFvGsDUQ+8jthe5drRfMfHr/znwbQjm3RCRSXaTAuLoWb+xlhEXI1ouUDPeFNE+jibkWyG+fDs5Q=="], + "@wrnexus/ssr": ["@wrnexus/ssr@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/security": "^0.8.5", "@wrnexus/store": "^0.8.5" } }, "sha512-Ju27nwR3SoupXvkTYwRqNXTgHaxB1XpN03LO7pHFV2QTw9zAvsAx818A99g5PmZoN87VuJX51kz+Dnqy5FoBow=="], - "@wrnexus/styles": ["@wrnexus/styles@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/uploader": "^0.8.4" } }, "sha512-55wSVTQjGrMy8lhODl+sQ+MMiF7Gjg2XdPMkl211YUd65km0cSYsOmEiqhbFLlwMQZj2+VP5KTMKjqspb66USQ=="], + "@wrnexus/store": ["@wrnexus/store@0.8.5", "", {}, "sha512-d52gERyyfqNd3kwiRbQ9+y8BxhP3VxckwCE6BU+vB4DYvMFAD6b0R4sAYSKgbO4gU8QS4vbO4blNXTyaeHlc0A=="], - "@wrnexus/syntax": ["@wrnexus/syntax@0.8.4", "", {}, "sha512-KEcTAtGgE+Wx53sO1ZXhKPr+sptmHBIzLJ8WeHQEyO4y9qimd4hFwkQ/nkIhnz44uxPkkBUho2comRjCl3Z9YA=="], + "@wrnexus/styles": ["@wrnexus/styles@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/uploader": "^0.8.5" } }, "sha512-aSuvyiHGWTFKOPnUPsfybE5hFXQFnz1cIFluGkd0ACE3F8x83YzaM6rheCADvRvDfEUDVor40VD1QEEYNawmUQ=="], - "@wrnexus/test": ["@wrnexus/test@0.8.4", "", {}, "sha512-PaoQCqzyGyl1klQGnpinKvzmznQD2FWuZA/qfb37+Z2latvD3sd4K3Ta5HN5Mg1xJ8WZfYmNRmm4xT2Z/FetOg=="], + "@wrnexus/syntax": ["@wrnexus/syntax@0.8.5", "", {}, "sha512-6MHmdzR1D+/gD6cXdbOgzzgj6I62VCyRVmtx8sa+qHrrcftdARj5OI/YyjyMGpHKdOCx4rGUhOCrSkjjiKgPDg=="], - "@wrnexus/tracking": ["@wrnexus/tracking@0.8.4", "", {}, "sha512-QKfMmoh5rJHbYbrznD+o3PR55fzi7JP4/WKAHJavYBugidQVLaw0EYrfTBITGmu+wh0ffQcG8SgNUx7APPdDhQ=="], + "@wrnexus/test": ["@wrnexus/test@0.8.5", "", {}, "sha512-dNGayxozSDjDYOlnR5cPYZfX4lIxrksCAFKHTDWHfpKd/UmLCj2BvarSF1hKsZf7PcKwy3U1T+unMPRwf56ghg=="], - "@wrnexus/typecheck": ["@wrnexus/typecheck@0.8.4", "", { "dependencies": { "@wrnexus/syntax": "^0.8.4", "typescript": "^5.5.0" } }, "sha512-NGmYpDrBMkF21VpeQK+kMIV8CoxySG0TzOkZBBbN/rW07JvkqKRUmS65DSd9lzLCnmrWfOxWdh3hjWvJCK/FaA=="], + "@wrnexus/tracking": ["@wrnexus/tracking@0.8.5", "", {}, "sha512-UZ0Z9yJ7I4XxAcsfOONPKgcjXdyD9qIgUGqRZvZ3yT6WCI1vSYedZb1hhIdHZ2romWOmiHaEut+tto95NivLOQ=="], - "@wrnexus/ui": ["@wrnexus/ui@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4" } }, "sha512-oZhN3gDkwbHTY/9YabSZtCv5zrlvN/OKWS4jGiWCqGp1NgNVmuy5nZdiLFbpug9uZZrl27iIMJpdyAqI/rCH1A=="], + "@wrnexus/typecheck": ["@wrnexus/typecheck@0.8.5", "", { "dependencies": { "@wrnexus/syntax": "^0.8.5", "typescript": "^5.5.0" } }, "sha512-O8Y2CbReia1zUBeSNLXNa9qpp0js4uUMmhE2yvM6lu4mh5Iw/6It2VgQH910zstPx6mDnnQlpTF5S/x+X1Oocg=="], - "@wrnexus/uploader": ["@wrnexus/uploader@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/ui": "^0.8.4" } }, "sha512-rR5/Acul7gH87aEsYtvlPMWn/JCXNhNyFf6aiWOkf3XR42zD50J6l9BeOF3BaHrTXbnA81jmBj3xhEmNPvLiWw=="], + "@wrnexus/ui": ["@wrnexus/ui@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5" } }, "sha512-9ZjOAZ1gGJs2v1AYY8tJQd24MqYV8xxyjlII3JFiYXt0Ek5EGlpY4l79i8zVCxWwQXrCkt1xWlacOM7F6hzdJA=="], - "@wrnexus/validation": ["@wrnexus/validation@0.8.4", "", { "dependencies": { "@wrnexus/core": "^0.8.4", "@wrnexus/plugin": "^0.8.4", "@wrnexus/ui": "^0.8.4" } }, "sha512-OCtaLnTrnn9SrhvKBjThXOdB0ba0m2HylSOd72XGyCFituCIcFpUGf1gW/MUWZ9JdtBvdK2W2FVHPnYMUVIc5Q=="], + "@wrnexus/uploader": ["@wrnexus/uploader@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/ui": "^0.8.5" } }, "sha512-rk0VipXH5B3oWR1qsb1NLtZ2tSraRzwlgbMP/GC8UpzFdW2hCOwFAa9u5dES1sPEGqTlcHoK9xLherSRfaB6KQ=="], + + "@wrnexus/validation": ["@wrnexus/validation@0.8.5", "", { "dependencies": { "@wrnexus/core": "^0.8.5", "@wrnexus/plugin": "^0.8.5", "@wrnexus/ui": "^0.8.5" } }, "sha512-qtSEu3qRgxhyUu+3fhMr4pR6PaBHUtTnDqI/UeQ+u0buMx06j54iXvy8TW7dwe8QVvY5AmY8zvT5jaeYlKt1xA=="], "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="], diff --git a/docs/documentation-coverage-matrix.md b/docs/documentation-coverage-matrix.md index 2a41addc..7eb837d8 100644 --- a/docs/documentation-coverage-matrix.md +++ b/docs/documentation-coverage-matrix.md @@ -37,6 +37,7 @@ | @wrnexus/reactive | /packages/reactive | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | | @wrnexus/realtime | /packages/realtime | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | | @wrnexus/router | /packages/router | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/rpc | /packages/rpc | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | | @wrnexus/security | /packages/security | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | | @wrnexus/ssr | /packages/ssr | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | | @wrnexus/store | /packages/store | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | diff --git a/docs/release-access-status.md b/docs/release-access-status.md index 2f7df814..ca9d6575 100644 --- a/docs/release-access-status.md +++ b/docs/release-access-status.md @@ -2,6 +2,6 @@ ## Decision: Mode B — Private Developer Preview -Active version: 0.8.4, derived from package.json#wrnexus.version. All 46 installed @wrnexus packages resolve to 0.8.4 and npm reports restricted access. The repository remote is a private WorkRoot Git service and no public license file exists. +Active version: 0.8.5, derived from package.json#wrnexus.version. All 47 installed @wrnexus packages resolve to 0.8.5 and npm reports restricted access. The repository remote is a private WorkRoot Git service and no public license file exists. -External users cannot execute an installation without approved private registry credentials. The truthful CTA is Request preview access. After approval, the canonical command is bunx @wrnexus/cli@0.8.4 create my-app. Tokens must never appear in documentation or source. +External users cannot execute an installation without approved private registry credentials. The truthful CTA is Request preview access. After approval, the canonical command is bunx @wrnexus/cli@0.8.5 create my-app. Tokens must never appear in documentation or source. diff --git a/docs/site-audit.md b/docs/site-audit.md index 20f16aee..8320ef40 100644 --- a/docs/site-audit.md +++ b/docs/site-audit.md @@ -1,18 +1,18 @@ # WRNexusJS site audit -Date: 2026-07-13. Baseline: Bun 1.3.14, framework 0.8.4. +Date: 2026-07-13. Baseline: Bun 1.3.14, framework 0.8.5. ## Baseline results - authenticated private-registry installation: pass. -- docs generation: pass (46 package pages plus portal and guide pages). +- docs generation: pass (47 package pages plus portal and guide pages). - tests, lint, formatting, and production build are required by the release check. - package access remains restricted/private. - repository: private WorkRoot Git remote; no public license file exists. ## Findings -Package documentation, discovery assets, and AI-readable references are generated from the installed release. The 0.8.4 portal includes the helpers package, workspace app addition, and safe forward-auth login redirect guidance. +Package documentation, discovery assets, and AI-readable references are generated from the installed release. The 0.8.5 portal includes the helpers package, workspace app addition, and safe forward-auth login redirect guidance. ## Audit limitations diff --git a/package-lock.json b/package-lock.json index a590da1d..c8517a92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,58 +10,59 @@ "dependencies": { "@iconify-json/lucide": "^1.2.118", "@iconify/tailwind4": "^1.2.3", - "@wrnexus/ai": "^0.8.4", - "@wrnexus/auth": "^0.8.4", - "@wrnexus/authz": "^0.8.4", - "@wrnexus/benchmark": "^0.8.4", - "@wrnexus/cache": "^0.8.4", - "@wrnexus/captcha": "^0.8.4", - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/content": "^0.8.4", - "@wrnexus/core": "^0.8.4", - "@wrnexus/csr": "^0.8.4", - "@wrnexus/db": "^0.8.4", - "@wrnexus/dev-server": "^0.8.4", - "@wrnexus/dev-toolbar": "^0.8.4", - "@wrnexus/encryption": "^0.8.4", - "@wrnexus/graphql": "^0.8.4", - "@wrnexus/helpers": "^0.8.4", - "@wrnexus/i18n": "^0.8.4", - "@wrnexus/identity": "^0.8.4", - "@wrnexus/image": "^0.8.4", - "@wrnexus/jwt": "^0.8.4", - "@wrnexus/language-server": "^0.8.4", - "@wrnexus/mcp": "^0.8.4", - "@wrnexus/mobile": "^0.8.4", - "@wrnexus/native": "^0.8.4", - "@wrnexus/oauth": "^0.8.4", - "@wrnexus/observability": "^0.8.4", - "@wrnexus/playground": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/pubsub": "^0.8.4", - "@wrnexus/pwa": "^0.8.4", - "@wrnexus/queue": "^0.8.4", - "@wrnexus/reactive": "^0.8.4", - "@wrnexus/realtime": "^0.8.4", - "@wrnexus/router": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/ssr": "^0.8.4", - "@wrnexus/store": "^0.8.4", - "@wrnexus/styles": "^0.8.4", - "@wrnexus/syntax": "^0.8.4", - "@wrnexus/test": "^0.8.4", - "@wrnexus/tracking": "^0.8.4", - "@wrnexus/typecheck": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/uploader": "^0.8.4", - "@wrnexus/validation": "^0.8.4" + "@wrnexus/ai": "^0.8.5", + "@wrnexus/auth": "^0.8.5", + "@wrnexus/authz": "^0.8.5", + "@wrnexus/benchmark": "^0.8.5", + "@wrnexus/cache": "^0.8.5", + "@wrnexus/captcha": "^0.8.5", + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/content": "^0.8.5", + "@wrnexus/core": "^0.8.5", + "@wrnexus/csr": "^0.8.5", + "@wrnexus/db": "^0.8.5", + "@wrnexus/dev-server": "^0.8.5", + "@wrnexus/dev-toolbar": "^0.8.5", + "@wrnexus/encryption": "^0.8.5", + "@wrnexus/graphql": "^0.8.5", + "@wrnexus/helpers": "^0.8.5", + "@wrnexus/i18n": "^0.8.5", + "@wrnexus/identity": "^0.8.5", + "@wrnexus/image": "^0.8.5", + "@wrnexus/jwt": "^0.8.5", + "@wrnexus/language-server": "^0.8.5", + "@wrnexus/mcp": "^0.8.5", + "@wrnexus/mobile": "^0.8.5", + "@wrnexus/native": "^0.8.5", + "@wrnexus/oauth": "^0.8.5", + "@wrnexus/observability": "^0.8.5", + "@wrnexus/playground": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/pubsub": "^0.8.5", + "@wrnexus/pwa": "^0.8.5", + "@wrnexus/queue": "^0.8.5", + "@wrnexus/reactive": "^0.8.5", + "@wrnexus/realtime": "^0.8.5", + "@wrnexus/router": "^0.8.5", + "@wrnexus/rpc": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/ssr": "^0.8.5", + "@wrnexus/store": "^0.8.5", + "@wrnexus/styles": "^0.8.5", + "@wrnexus/syntax": "^0.8.5", + "@wrnexus/test": "^0.8.5", + "@wrnexus/tracking": "^0.8.5", + "@wrnexus/typecheck": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/uploader": "^0.8.5", + "@wrnexus/validation": "^0.8.5" }, "devDependencies": { "@eslint/js": "^9.0.0", "@tailwindcss/cli": "^4.0.0", "@types/bun": "latest", "@types/node": "^26.1.1", - "@wrnexus/cli": "^0.8.4", + "@wrnexus/cli": "^0.8.5", "eslint": "^9.0.0", "prettier": "latest", "tailwindcss": "^4.0.0", @@ -1503,104 +1504,109 @@ } }, "node_modules/@wrnexus/ai": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/ai/-/ai-0.8.4.tgz", - "integrity": "sha512-iL391Ka6ompz7NcdfFtvEDOCqPKGz+VCJQN3xIbQERBJ131zpXxa9GQF3myR7w3gtiydLGnajiqbRgpbTG5VvQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/ai/-/ai-0.8.5.tgz", + "integrity": "sha512-TLRbvepuMnIZmsmMH/5cTzHfdkvK2+lNU+CX/2DIRHAC8/ghz2wpp7ZVv/J6LU7shygJx/IDDOJfKlAAwFjEvA==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/auth": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/auth/-/auth-0.8.4.tgz", - "integrity": "sha512-N86/29UaDWWqC5O2bgylQzhp0rwH3+KdVxQ1oBr1tIP7DKsNo7ZrlDaMH9RSbVbzhdLwEl4G1+a4lrHBr7UM6g==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/auth/-/auth-0.8.5.tgz", + "integrity": "sha512-6KbeRreKjew3LlY1u5t681nrzZzVMT19hFCRFVeAsL8Avc/VzYqd5G6QdcV2ixDObz4pIktXJL/Yg4LfvzQZ+w==", "license": "MIT", "dependencies": { - "@wrnexus/authz": "^0.8.4", - "@wrnexus/captcha": "^0.8.4", - "@wrnexus/core": "^0.8.4", - "@wrnexus/db": "^0.8.4", - "@wrnexus/encryption": "^0.8.4", - "@wrnexus/jwt": "^0.8.4", - "@wrnexus/oauth": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/queue": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/validation": "^0.8.4" + "@wrnexus/authz": "^0.8.5", + "@wrnexus/captcha": "^0.8.5", + "@wrnexus/core": "^0.8.5", + "@wrnexus/db": "^0.8.5", + "@wrnexus/encryption": "^0.8.5", + "@wrnexus/jwt": "^0.8.5", + "@wrnexus/oauth": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/queue": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/validation": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/authz": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/authz/-/authz-0.8.4.tgz", - "integrity": "sha512-oyQl6HtzsUPhw9yDENNRopF6n9tq+yPbZU5q97gvGaQ8n7AzzlW/y6f9uNEYGXjZZjcBopCAeqVireZGLDw+3Q==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/authz/-/authz-0.8.5.tgz", + "integrity": "sha512-tgtnNkPp+qVk0W6Tq/Kn4PXsbD14mAEpGKhvNyHwqY/fU5zp3D+1L+RjiWPA2r0+qOhfePOJdgBFvbODAdBcrA==", "license": "MIT", + "dependencies": { + "@wrnexus/core": "^0.8.5", + "@wrnexus/db": "^0.8.5" + }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/benchmark": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/benchmark/-/benchmark-0.8.4.tgz", - "integrity": "sha512-vck4FcNHggvIuGMdSxbu+NYedAtmVXGsbPNC8FpmhZ7lJviDAv1gqHf4YW33MA9x8yWdwQAHIygSy68pdPYbbA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/benchmark/-/benchmark-0.8.5.tgz", + "integrity": "sha512-PjtCCI7KUuKQW1k2K0apjVnvUIPocPmxOJii/TnsxgzNYE5W22IFux5rOK93sM2zUJVB6aUaR4jQhCxctUMjsg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/cache": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/cache/-/cache-0.8.4.tgz", - "integrity": "sha512-twzmNRylE6PNu63xt2j9cNjKm+AhhcscVaXbPMbsWN7sKuL4O0kC/Iny0elD1jtXt3xAG4iayOzCiaxLhtEbUg==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/cache/-/cache-0.8.5.tgz", + "integrity": "sha512-d3SXerkaUArgWo68FXdyr2owtji9cSHEsMH6bkQIAgFh3BvbQn5nvA+BHX37EqUAWpMcOMfSG9tw08kLFgBTHA==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/captcha": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/captcha/-/captcha-0.8.4.tgz", - "integrity": "sha512-8KubI7v6NsfJRhJB+OgHNJSDsDgtLlWBLcxYBv+C0YE7QTdD96NNJ3X0m9e/aAYwGlKChLW/pc7iVQ4/Uv1vxQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/captcha/-/captcha-0.8.5.tgz", + "integrity": "sha512-QFH+MXxiIZWEfZDUm28pJcCkDkRFb7Dehw4URscuMZar4wCrWCsE+xdhtHZiNiaBqwfSwWFqcH2qVjweT/ZVDg==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/validation": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/validation": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/cli": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/cli/-/cli-0.8.4.tgz", - "integrity": "sha512-1xnKsbWWKxIQaZD9sDBAzmSYsRU2+7vcq0IQotoHHKcRwV06myda4kcTQcFMpzELr9Um/to7gYIXC274f1k0Vw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/cli/-/cli-0.8.5.tgz", + "integrity": "sha512-k0QOLnDrDY/gNzY3VTEZgYhobI3xJH0xjqjdVr2/6VBxkmuDXqZt1vOLS37p5ugbfpLOw+aIrcfQ8iG4u3w2iw==", "dev": true, "license": "MIT", "dependencies": { - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/core": "^0.8.4", - "@wrnexus/csr": "^0.8.4", - "@wrnexus/db": "^0.8.4", - "@wrnexus/dev-server": "^0.8.4", - "@wrnexus/i18n": "^0.8.4", - "@wrnexus/mcp": "^0.8.4", - "@wrnexus/playground": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/router": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/styles": "^0.8.4", - "@wrnexus/syntax": "^0.8.4", - "@wrnexus/typecheck": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/validation": "^0.8.4", + "@wrnexus/authz": "^0.8.5", + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/core": "^0.8.5", + "@wrnexus/csr": "^0.8.5", + "@wrnexus/db": "^0.8.5", + "@wrnexus/dev-server": "^0.8.5", + "@wrnexus/i18n": "^0.8.5", + "@wrnexus/mcp": "^0.8.5", + "@wrnexus/playground": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/router": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/styles": "^0.8.5", + "@wrnexus/syntax": "^0.8.5", + "@wrnexus/typecheck": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/validation": "^0.8.5", "selfsigned": "^5.5.0" }, "bin": { @@ -1611,196 +1617,198 @@ } }, "node_modules/@wrnexus/compiler": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/compiler/-/compiler-0.8.4.tgz", - "integrity": "sha512-8t+rrBE1WVKUTUFSkktFGbEz2Hy62bwKvOs2/b9pTse9N3oqwlpg7NmGUue7N46x5jjDmOk8xSoKAzX3OG1QaQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/compiler/-/compiler-0.8.5.tgz", + "integrity": "sha512-+jU7J8SBsDylMw22y5LiK1R80Etv5o5uX5bELGVxiKD/au2rw6JTFI7ERxVFjw4i4C1ASnwkfA6pnbUzbdP6Lw==", "license": "MIT", "dependencies": { - "@wrnexus/csr": "^0.8.4", - "@wrnexus/store": "^0.8.4", - "@wrnexus/syntax": "^0.8.4", - "@wrnexus/validation": "^0.8.4" + "@wrnexus/csr": "^0.8.5", + "@wrnexus/store": "^0.8.5", + "@wrnexus/syntax": "^0.8.5", + "@wrnexus/validation": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/content": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/content/-/content-0.8.4.tgz", - "integrity": "sha512-1PUuUJeT/yOVC/OldUAqdQ2JH3SZiynuBK+Q2nlqir+W0mC6I4ezkG7paewIWh8N+FPXY3N485IlUrGMgAQi9A==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/content/-/content-0.8.5.tgz", + "integrity": "sha512-pD7gqEY+phI4ggfQ7/SG927GgPSUkGDHk3mXSAFJmIQl2xoeVRlLSilbnYOaHT8+rR4Fx/zMuGNhu2SCOMk/Ag==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/core": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/core/-/core-0.8.4.tgz", - "integrity": "sha512-7Vk7Xbjlw9sNbpljFAE2Np6CCyb09LJRKJqDmLsoc54wopS6RIPBfJXAbsezNdwh7EiTFsIyQ/KwojZUQf9hPA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/core/-/core-0.8.5.tgz", + "integrity": "sha512-mKPNgOKa68T1056Z/Ond1WL7qBT2pDvG72WQfdQ4Z8+XQ9aQXLr5tikBtoUOW5xj9mQdQLJ3Di4tqjhjCMoR1g==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/csr": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/csr/-/csr-0.8.4.tgz", - "integrity": "sha512-hTjZYET+SMNuc4B3tMUJXmmmapi6MdTN8V7PpfhCBsGnurP+oufR7r1ayWCakjt6y2PINp1/nUdO2Wz03H1V+A==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/csr/-/csr-0.8.5.tgz", + "integrity": "sha512-e1kh6PyA9CnzVmbQRcvBPvkJzsIWP4Z6HDppFDOymwIKPf7/aFck2u7r5pM9XDLLuNaJOPyq2BOfj1a/vF1yUQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/db": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/db/-/db-0.8.4.tgz", - "integrity": "sha512-y890w4Kpb+Ve7gMI+CCbgMtzXgxvHFiMtsY8ODBHxs7G0DVheUehmnfNxmajh4ufxO3co20j5h7lx9vyD3/+og==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/db/-/db-0.8.5.tgz", + "integrity": "sha512-cRLPfh+4+0iOTrWW5HqMiHRyUdmQLMAdtSPeB9XkCSctUZFfRGjKRpqnlgzglh4q2TijFymSiJUpVCut84KpLA==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/dev-server": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/dev-server/-/dev-server-0.8.4.tgz", - "integrity": "sha512-UKyLaIsZTEtPN3OgPxyV6LCirNXBOcGDY/vFL4egTInIYzWTMH0qxq/pKfm7CFztcQqBVRBlyO9/nCqeZet7FQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/dev-server/-/dev-server-0.8.5.tgz", + "integrity": "sha512-kSztqn4b+eeJeAadT+fWxVCxG2jXGrrxWbzOBHTGzN2KI4Z8nHlvJZCY1XOpUUCsGwKfF6jC29n2L5N0DBjYNQ==", "license": "MIT", "dependencies": { - "@wrnexus/cache": "^0.8.4", - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/core": "^0.8.4", - "@wrnexus/csr": "^0.8.4", - "@wrnexus/db": "^0.8.4", - "@wrnexus/dev-toolbar": "^0.8.4", - "@wrnexus/i18n": "^0.8.4", - "@wrnexus/observability": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/pubsub": "^0.8.4", - "@wrnexus/pwa": "^0.8.4", - "@wrnexus/router": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/ssr": "^0.8.4", - "@wrnexus/store": "^0.8.4", - "@wrnexus/styles": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/uploader": "^0.8.4", - "@wrnexus/validation": "^0.8.4" + "@wrnexus/authz": "^0.8.5", + "@wrnexus/cache": "^0.8.5", + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/core": "^0.8.5", + "@wrnexus/csr": "^0.8.5", + "@wrnexus/db": "^0.8.5", + "@wrnexus/dev-toolbar": "^0.8.5", + "@wrnexus/i18n": "^0.8.5", + "@wrnexus/observability": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/pubsub": "^0.8.5", + "@wrnexus/pwa": "^0.8.5", + "@wrnexus/router": "^0.8.5", + "@wrnexus/rpc": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/ssr": "^0.8.5", + "@wrnexus/store": "^0.8.5", + "@wrnexus/styles": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/uploader": "^0.8.5", + "@wrnexus/validation": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/dev-toolbar": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.4.tgz", - "integrity": "sha512-dpXfAyZ+WL5aWrl0Gw1ddKIpxd8Wirq8hAbVFQ84fNSE27yyIUpr5tXIk15MstB9xv3W1o6Ufiotv8iGp7EwbQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.5.tgz", + "integrity": "sha512-gIg/OQlAD63XRtQ0ncAu6RuDQaVTOYgBxUSgIB6dq4+LZQGsKgv7GZMej5LwGOJsw1eU1+X7qtUqJ8GWiWQNSw==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/encryption": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/encryption/-/encryption-0.8.4.tgz", - "integrity": "sha512-3mB/3qBZdvJ2YaiTf6Gjs52uCIfzoxTS0sykvruAkslbKNKVW8iI3NYlZohoIVp6ZuqP86CnTZCxG/EhHi6N+Q==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/encryption/-/encryption-0.8.5.tgz", + "integrity": "sha512-nfqb2DJ2FHGozkfxrxOeNrb96fZ4X5IJXM0DCF0Ix75nnHFcYEVc2MXll1uoQt0K6YYUl27NzVx2W7Sakz6hFA==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/graphql": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/graphql/-/graphql-0.8.4.tgz", - "integrity": "sha512-rdlQ3t/X9XIGRs9CnUjZMSbop5X/IpzsRE36fRV0t2vpDGoUFPt9igvg05Hla09rPcnXQyrNtIxW4BjPdsqwwA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/graphql/-/graphql-0.8.5.tgz", + "integrity": "sha512-/9+ONokYh9b3ZiLT8XVz8BQNOTsPjYHx6TG74X4YpkG4wpIYB7T2aWzgheAeHg/qPy3l17gbQiMDnH9VzEU3/g==", "license": "MIT", "dependencies": { - "@wrnexus/plugin": "^0.8.4" + "@wrnexus/plugin": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/helpers": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/helpers/-/helpers-0.8.4.tgz", - "integrity": "sha512-RkPVULBY9amUXo0S7UDWxXv9KnFbzj0rO8l3YNKR7CGGcUnl4C77gFMyjDez8mlavjZannpXaMdh4RMuT6bDxQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/helpers/-/helpers-0.8.5.tgz", + "integrity": "sha512-2FHTuCklh4JKv3w0bfNW2qm/ulweSvluFF0GoIG7EVjBxP6AQO6JyaaZVddd/7N1k5Klnbir9+aiDBgcbf5gWQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/i18n": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/i18n/-/i18n-0.8.4.tgz", - "integrity": "sha512-wSbnxETNycQzbZy8V39B0ZsmZYez8qaEs5e6ODAR+k+3FY//G5CYQxARJxeQAQ7wL3qaLoEBmPxG3eySXnOCPg==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/i18n/-/i18n-0.8.5.tgz", + "integrity": "sha512-9VgDK6pjVk7QPG/WYtDmqLw2myBKTMHu5Bl39rX52yJY6bm6W9o+/bFZ14x3IlJ66JFO+XTkHviC2RnQwUD8TQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/ui": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/ui": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/identity": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/identity/-/identity-0.8.4.tgz", - "integrity": "sha512-uCI/4ThVSHvDIxQLJ669E9OtzMhi3+2JRjz6VHN5p3zuQbLOVDglMGOOuahLs3NrJTvOqy9fDtuTLVoKESTcDQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/identity/-/identity-0.8.5.tgz", + "integrity": "sha512-YUQ/8XunmUFEyHbqOhITHV5KgszJGLCDvGZvlXkHUzbia5B2nakYy0Gw+RsSumYCGcXmxalbSx+UhmMkHY+cfA==", "license": "MIT", "dependencies": { - "@wrnexus/auth": "^0.8.4", - "@wrnexus/authz": "^0.8.4", - "@wrnexus/oauth": "^0.8.4" + "@wrnexus/auth": "^0.8.5", + "@wrnexus/authz": "^0.8.5", + "@wrnexus/oauth": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/image": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/image/-/image-0.8.4.tgz", - "integrity": "sha512-BRDLAD8hUqkdjxSe/OVrkZTSd6o000jN2Ai1A41St+PS9/fmcNZgg2nZXcK30T12wxYoFCDAn++WshF3mEdf2w==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/image/-/image-0.8.5.tgz", + "integrity": "sha512-+Bf3DNaLQAw4oMYCw3U9wT1h6AGQH1uC7PjKPNsns1pxhpqeSjOOjLI3pI8HaWjeR9D9sZ3XaGqqV3ly7LFZ1g==", "license": "MIT", "dependencies": { - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/ui": "^0.8.4" + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/ui": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/jwt": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/jwt/-/jwt-0.8.4.tgz", - "integrity": "sha512-6QFRX7hBjLmmwMXggH1WOHop6fXQcqbP05YZPWDExLEC6MNBxaChs31ihSHkZczsxF5zmvPaLfrL80CpycXsFg==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/jwt/-/jwt-0.8.5.tgz", + "integrity": "sha512-tj3UnWR1Uqtrnon4+UNlHcI1pqgmk/ul4b+Oc9HynKd1r7OqO41P92AFgFTPHyeR1xRrl0/ELaIqpE/uIz4wrw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/language-server": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/language-server/-/language-server-0.8.4.tgz", - "integrity": "sha512-nk8no6MiPq5nFWbNiBIofU7GzTVW4viCr5K6ErxqyEbv2loQdPjV1YBR9z1D7EHbQlywMuJeV4OeIBiHxeuMew==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/language-server/-/language-server-0.8.5.tgz", + "integrity": "sha512-G2UmH+a9/9xxaJqqYeOHx/A1baj8TELCKy2ehoa/H1jB9ZbMl0GXkzUS0jZSHEDio6Ln2R1wpC6PvSIkwmAsWg==", "license": "MIT", "dependencies": { - "@wrnexus/syntax": "^0.8.4", - "@wrnexus/typecheck": "^0.8.4" + "@wrnexus/syntax": "^0.8.5", + "@wrnexus/typecheck": "^0.8.5" }, "bin": { "wrnexus-language-server": "dist/server.js" @@ -1810,9 +1818,9 @@ } }, "node_modules/@wrnexus/mcp": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/mcp/-/mcp-0.8.4.tgz", - "integrity": "sha512-1maJkJCCLLGggmO01eWIs2LgejBUxdR8aQO/HDuSuhI+vQvJrLlYBkqvjquVjr2Nlhv7ui7LBcLsVRAPBNw7Tw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/mcp/-/mcp-0.8.5.tgz", + "integrity": "sha512-xDcXX9sYkBOX5CHYTEi7zjPr0SRReyN+p9zvLQFjVK0WVv9TRws9FckSujyz1RNHjSf0PxK2vr9d0ibdxG33Pw==", "license": "MIT", "bin": { "wrnexus-mcp": "dist/stdio.js" @@ -1822,224 +1830,239 @@ } }, "node_modules/@wrnexus/mobile": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/mobile/-/mobile-0.8.4.tgz", - "integrity": "sha512-/63nsfwF1vZ9bHgPTuyd7F9ej9DRzPJJFx/H+fm9iXOD+ew15gBmPLwt7GJJWoUu99Wi2aiFVzM1/KVyy7gNqA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/mobile/-/mobile-0.8.5.tgz", + "integrity": "sha512-qHbwKp3TIAdRBEaV/7ixDA4LUyArsJZmOCGlTsrA2xQiO3YGvMNNsh9rjSqZuQO5tC1WrJVXMmOnMbtJf2jJjQ==", "license": "MIT", "dependencies": { - "@wrnexus/native": "^0.8.4" + "@wrnexus/native": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/native": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/native/-/native-0.8.4.tgz", - "integrity": "sha512-4llVTslb87a7qhAJUlFQ/PYbFrmsasKwOj9kgve02vo/IneiLJ4/QE1vGKVsUAgmdpt2picTwF/YyWssvQmBmg==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/native/-/native-0.8.5.tgz", + "integrity": "sha512-181rt4/KLBcCOcRe62N0Txx6fiJplsmz4e8F6nbC2gGKplxH+WYXfp0+ZeL6szXqhVBb/rbsZgRi9Xots/7xHw==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/oauth": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/oauth/-/oauth-0.8.4.tgz", - "integrity": "sha512-jl7T6KQkA96GLGJ3ZJCobaAiXsLvrcrH7d2VRIoITuHQtgJ3s/aC5BcfmqwokjT4guqEeC/K7CkD5bivbWvlPw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/oauth/-/oauth-0.8.5.tgz", + "integrity": "sha512-kkYXRaftZGcKnvm3UxlgUBnE6DWZ5/cTSj4LIJ3C4Y2j0vXdso+CSmPPzXM3TvPY/4d1NQMuBOB69JC83s70nA==", "license": "MIT", "dependencies": { - "@wrnexus/jwt": "^0.8.4" + "@wrnexus/jwt": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/observability": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/observability/-/observability-0.8.4.tgz", - "integrity": "sha512-VFji7+lNcZ0AXRHChw80rTwIYjkfyk4Cu9MvGp9uorNoWeYiI6ns4f6yhwIEtOG/5XwYIpytHNim5TPtOdzk3g==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/observability/-/observability-0.8.5.tgz", + "integrity": "sha512-gEWx5mruRElJbCKTYRFdncotXHJOqw7Bzm41dcR+NVvkZlV8ome+s8f8XPzlJWpYmFYVzGj9N0ev14AP3ax9kw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/playground": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/playground/-/playground-0.8.4.tgz", - "integrity": "sha512-Y/gx/VIKhAazUTSSQaN4Hr3akzeTjsFkUj03kqWHY5NQUNlk874hYDksdFVKjtMbj2I3npxq4ADLr2l9+HEc5w==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/playground/-/playground-0.8.5.tgz", + "integrity": "sha512-8saMjmZfRiFXMlMa4qjyG66xfVqCoQhsW/KeIQUF/MkCFtm8FGkexgR5RANiH8wALD/d8uEMNnPMRg7B1iWymw==", "license": "MIT", "dependencies": { - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/syntax": "^0.8.4" + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/syntax": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/plugin": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/plugin/-/plugin-0.8.4.tgz", - "integrity": "sha512-1EiZt0NvpC3pH75TVbWM4GCWF/lS+9jlsIV3IMX/1I/QoXaABtWuRnXgSh7ROmVe1fE3hd1EwYGlWN9vWim4XA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/plugin/-/plugin-0.8.5.tgz", + "integrity": "sha512-PYgpNZ6dmJvv+DJUtv8rKd1SAQ0as12Y5UZcy0SpHU+ZUrrrOakwpOtAdXlKJTG1+1rsZjbdDVgFIauSnnOOpg==", "license": "MIT", "dependencies": { - "@wrnexus/syntax": "^0.8.4" + "@wrnexus/syntax": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/pubsub": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/pubsub/-/pubsub-0.8.4.tgz", - "integrity": "sha512-6RVg5x8jLGO2HIv0kX5RTq7TI0A+Ki1VnbB86yCW3Kl3F5ABwe5SJwDxkzVhz9RPCHn08+TStYpNrWKd4Ofx+g==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/pubsub/-/pubsub-0.8.5.tgz", + "integrity": "sha512-3XNKkRestcL8UDCM1GBWxbl6W5k1vx4Gi1XzpsWF9TrAf42wwFgYvdTrDknNqf58Mf7QGUAhwZFL/HN4AIH7/A==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/pwa": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/pwa/-/pwa-0.8.4.tgz", - "integrity": "sha512-xWB8WjCxaY7qtVkzhk6I9kPX5ReUtUdgKdaSFiWHNg5moeUEk2cVLmzWcOSKNRUEZ2vVos93vyaFIlTctR5/DQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/pwa/-/pwa-0.8.5.tgz", + "integrity": "sha512-mpXZqlD1M9OForvmdFPdjisZM+ymf7qpm2U7FvneogXxsUIrTSGUEtPg9QMKdw30WkTR4zqvEpCbfWaVOSkhIA==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/queue": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/queue/-/queue-0.8.4.tgz", - "integrity": "sha512-5osvXmVGnBuaLyboKzn5RPk/Vef/qpp0t83lAffoMDI7QkTD9rPBkStHvKiYqYB3tOXGE0x0o9LT1kuiorkuAQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/queue/-/queue-0.8.5.tgz", + "integrity": "sha512-2IT0Gj+THkyqu+8X/XfHn4JEkhd/MvYMIGv5al7WFDgmrOb20Ls6dfNDenoDmXjSWkLcACRRXYTX+Zxj6/2MKQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/reactive": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/reactive/-/reactive-0.8.4.tgz", - "integrity": "sha512-1G1DY39jfkuqTDh2XfQfh+5oCL1CNTwEnHw65SNrX4L6KrWKLWy+dEYxCZ6dJNUFYvP+9jsz9H5DsvspAutSCw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/reactive/-/reactive-0.8.5.tgz", + "integrity": "sha512-ccRzjvXz5PZDajFBJ4pclQ9AIFrFpn8ZAwgi+OSiQJSr6elDVdx+lDNQXngkfK2OuJyBvkZNg/7GLnT9sbm6eg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/realtime": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/realtime/-/realtime-0.8.4.tgz", - "integrity": "sha512-F9gi6R9PV84k3uXTnWva2Y2NTUloLluG1GIibP2uuGNvii9Osp30+wYAWQKL2E8rDoGQTZWGWBwmEY9Yjj8tkA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/realtime/-/realtime-0.8.5.tgz", + "integrity": "sha512-oGIF/RAmrlo2hrXRYNIwNDHNcdrUT0CYo5vXk3GDiXGTeDpIdoGxwP7qVYNYxTkqHvxJnA4Lls4MtZBD63nuqQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/ui": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/ui": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/router": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/router/-/router-0.8.4.tgz", - "integrity": "sha512-qb3kNnsoUB447V4LD9Fh2BudklBvWCX/ksEYT6/jLAbtBA1wtNpCzi1mkYXod5mZZhGT6gjrXwXyBb7ZZ6MvLw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/router/-/router-0.8.5.tgz", + "integrity": "sha512-vKwKHNynHGufqD2xjntGzvf0ZwFrqWWnrs7H3gbIg9cUfbD6zdaYYDEm0UpuEDR4A5g6Y2hvEcPTyncj+nIQjw==", "license": "MIT", "dependencies": { - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/core": "^0.8.4" + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/core": "^0.8.5" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/rpc": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/rpc/-/rpc-0.8.5.tgz", + "integrity": "sha512-qxG/GayQxN9iusJ50M4ybsXPwdJUYCEB0Pkghs7dG1B+FcKOrYDkysx+zwaQ3uYN8ugfL4hk2NPmczRow41x3w==", + "license": "MIT", + "dependencies": { + "@wrnexus/core": "^0.8.5", + "@wrnexus/helpers": "^0.8.5", + "@wrnexus/jwt": "^0.8.5", + "@wrnexus/validation": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/security": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/security/-/security-0.8.4.tgz", - "integrity": "sha512-UPOdf2w29ae80GPG1k6aQ4xvfxlwTG/+4ADPqfKmJzgTjRX+rKyzX80TOGPN9q3h2DBqEJjMCWN86gQAvPLiMA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/security/-/security-0.8.5.tgz", + "integrity": "sha512-JJ2kzLdlWv3BuixJIi4HwMEk6Ke+gLmvINVJf5JInxsqc+hpikGyPDdkgCsY/6uS0ZS4vnFOiHs7GgmLwPQ33g==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/ssr": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/ssr/-/ssr-0.8.4.tgz", - "integrity": "sha512-1JZjTwfTFMZAPA43TkPlgNI0qd1b8YJNIPtDzpTgdUA7PVK0umiIMffTFCv7wY1lLtGYckgblI3Dg+JOQgVpHg==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/ssr/-/ssr-0.8.5.tgz", + "integrity": "sha512-Ju27nwR3SoupXvkTYwRqNXTgHaxB1XpN03LO7pHFV2QTw9zAvsAx818A99g5PmZoN87VuJX51kz+Dnqy5FoBow==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/store": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/store": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/store": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/store/-/store-0.8.4.tgz", - "integrity": "sha512-etkNk/6nzuTFvGsDUQ+8jthe5drRfMfHr/znwbQjm3RCRSXaTAuLoWb+xlhEXI1ouUDPeFNE+jibkWyG+fDs5Q==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/store/-/store-0.8.5.tgz", + "integrity": "sha512-d52gERyyfqNd3kwiRbQ9+y8BxhP3VxckwCE6BU+vB4DYvMFAD6b0R4sAYSKgbO4gU8QS4vbO4blNXTyaeHlc0A==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/styles": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/styles/-/styles-0.8.4.tgz", - "integrity": "sha512-55wSVTQjGrMy8lhODl+sQ+MMiF7Gjg2XdPMkl211YUd65km0cSYsOmEiqhbFLlwMQZj2+VP5KTMKjqspb66USQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/styles/-/styles-0.8.5.tgz", + "integrity": "sha512-aSuvyiHGWTFKOPnUPsfybE5hFXQFnz1cIFluGkd0ACE3F8x83YzaM6rheCADvRvDfEUDVor40VD1QEEYNawmUQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/uploader": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/uploader": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/syntax": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/syntax/-/syntax-0.8.4.tgz", - "integrity": "sha512-KEcTAtGgE+Wx53sO1ZXhKPr+sptmHBIzLJ8WeHQEyO4y9qimd4hFwkQ/nkIhnz44uxPkkBUho2comRjCl3Z9YA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/syntax/-/syntax-0.8.5.tgz", + "integrity": "sha512-6MHmdzR1D+/gD6cXdbOgzzgj6I62VCyRVmtx8sa+qHrrcftdARj5OI/YyjyMGpHKdOCx4rGUhOCrSkjjiKgPDg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/test": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/test/-/test-0.8.4.tgz", - "integrity": "sha512-PaoQCqzyGyl1klQGnpinKvzmznQD2FWuZA/qfb37+Z2latvD3sd4K3Ta5HN5Mg1xJ8WZfYmNRmm4xT2Z/FetOg==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/test/-/test-0.8.5.tgz", + "integrity": "sha512-dNGayxozSDjDYOlnR5cPYZfX4lIxrksCAFKHTDWHfpKd/UmLCj2BvarSF1hKsZf7PcKwy3U1T+unMPRwf56ghg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/tracking": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/tracking/-/tracking-0.8.4.tgz", - "integrity": "sha512-QKfMmoh5rJHbYbrznD+o3PR55fzi7JP4/WKAHJavYBugidQVLaw0EYrfTBITGmu+wh0ffQcG8SgNUx7APPdDhQ==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/tracking/-/tracking-0.8.5.tgz", + "integrity": "sha512-UZ0Z9yJ7I4XxAcsfOONPKgcjXdyD9qIgUGqRZvZ3yT6WCI1vSYedZb1hhIdHZ2romWOmiHaEut+tto95NivLOQ==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/typecheck": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/typecheck/-/typecheck-0.8.4.tgz", - "integrity": "sha512-NGmYpDrBMkF21VpeQK+kMIV8CoxySG0TzOkZBBbN/rW07JvkqKRUmS65DSd9lzLCnmrWfOxWdh3hjWvJCK/FaA==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/typecheck/-/typecheck-0.8.5.tgz", + "integrity": "sha512-O8Y2CbReia1zUBeSNLXNa9qpp0js4uUMmhE2yvM6lu4mh5Iw/6It2VgQH910zstPx6mDnnQlpTF5S/x+X1Oocg==", "license": "MIT", "dependencies": { - "@wrnexus/syntax": "^0.8.4", + "@wrnexus/syntax": "^0.8.5", "typescript": "^5.5.0" }, "engines": { @@ -2047,40 +2070,40 @@ } }, "node_modules/@wrnexus/ui": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/ui/-/ui-0.8.4.tgz", - "integrity": "sha512-oZhN3gDkwbHTY/9YabSZtCv5zrlvN/OKWS4jGiWCqGp1NgNVmuy5nZdiLFbpug9uZZrl27iIMJpdyAqI/rCH1A==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/ui/-/ui-0.8.5.tgz", + "integrity": "sha512-9ZjOAZ1gGJs2v1AYY8tJQd24MqYV8xxyjlII3JFiYXt0Ek5EGlpY4l79i8zVCxWwQXrCkt1xWlacOM7F6hzdJA==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4" + "@wrnexus/core": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/uploader": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/uploader/-/uploader-0.8.4.tgz", - "integrity": "sha512-rR5/Acul7gH87aEsYtvlPMWn/JCXNhNyFf6aiWOkf3XR42zD50J6l9BeOF3BaHrTXbnA81jmBj3xhEmNPvLiWw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/uploader/-/uploader-0.8.5.tgz", + "integrity": "sha512-rk0VipXH5B3oWR1qsb1NLtZ2tSraRzwlgbMP/GC8UpzFdW2hCOwFAa9u5dES1sPEGqTlcHoK9xLherSRfaB6KQ==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/ui": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/ui": "^0.8.5" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/validation": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@wrnexus/validation/-/validation-0.8.4.tgz", - "integrity": "sha512-OCtaLnTrnn9SrhvKBjThXOdB0ba0m2HylSOd72XGyCFituCIcFpUGf1gW/MUWZ9JdtBvdK2W2FVHPnYMUVIc5Q==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@wrnexus/validation/-/validation-0.8.5.tgz", + "integrity": "sha512-qtSEu3qRgxhyUu+3fhMr4pR6PaBHUtTnDqI/UeQ+u0buMx06j54iXvy8TW7dwe8QVvY5AmY8zvT5jaeYlKt1xA==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/ui": "^0.8.4" + "@wrnexus/core": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/ui": "^0.8.5" }, "engines": { "bun": ">=1.3.0" diff --git a/package.json b/package.json index a4e132a3..099f4ae4 100644 --- a/package.json +++ b/package.json @@ -27,58 +27,59 @@ "dependencies": { "@iconify-json/lucide": "^1.2.118", "@iconify/tailwind4": "^1.2.3", - "@wrnexus/ai": "^0.8.4", - "@wrnexus/authz": "^0.8.4", - "@wrnexus/compiler": "^0.8.4", - "@wrnexus/core": "^0.8.4", - "@wrnexus/csr": "^0.8.4", - "@wrnexus/db": "^0.8.4", - "@wrnexus/dev-server": "^0.8.4", - "@wrnexus/encryption": "^0.8.4", - "@wrnexus/helpers": "^0.8.4", - "@wrnexus/i18n": "^0.8.4", - "@wrnexus/jwt": "^0.8.4", - "@wrnexus/mobile": "^0.8.4", - "@wrnexus/native": "^0.8.4", - "@wrnexus/oauth": "^0.8.4", - "@wrnexus/pubsub": "^0.8.4", - "@wrnexus/queue": "^0.8.4", - "@wrnexus/reactive": "^0.8.4", - "@wrnexus/router": "^0.8.4", - "@wrnexus/ssr": "^0.8.4", - "@wrnexus/styles": "^0.8.4", - "@wrnexus/test": "^0.8.4", - "@wrnexus/tracking": "^0.8.4", - "@wrnexus/ui": "^0.8.4", - "@wrnexus/uploader": "^0.8.4", - "@wrnexus/validation": "^0.8.4", - "@wrnexus/dev-toolbar": "^0.8.4", - "@wrnexus/syntax": "^0.8.4", - "@wrnexus/plugin": "^0.8.4", - "@wrnexus/captcha": "^0.8.4", - "@wrnexus/auth": "^0.8.4", - "@wrnexus/store": "^0.8.4", - "@wrnexus/typecheck": "^0.8.4", - "@wrnexus/security": "^0.8.4", - "@wrnexus/cache": "^0.8.4", - "@wrnexus/image": "^0.8.4", - "@wrnexus/observability": "^0.8.4", - "@wrnexus/benchmark": "^0.8.4", - "@wrnexus/realtime": "^0.8.4", - "@wrnexus/content": "^0.8.4", - "@wrnexus/graphql": "^0.8.4", - "@wrnexus/identity": "^0.8.4", - "@wrnexus/language-server": "^0.8.4", - "@wrnexus/mcp": "^0.8.4", - "@wrnexus/playground": "^0.8.4", - "@wrnexus/pwa": "^0.8.4" + "@wrnexus/ai": "^0.8.5", + "@wrnexus/authz": "^0.8.5", + "@wrnexus/compiler": "^0.8.5", + "@wrnexus/core": "^0.8.5", + "@wrnexus/csr": "^0.8.5", + "@wrnexus/db": "^0.8.5", + "@wrnexus/dev-server": "^0.8.5", + "@wrnexus/encryption": "^0.8.5", + "@wrnexus/helpers": "^0.8.5", + "@wrnexus/i18n": "^0.8.5", + "@wrnexus/jwt": "^0.8.5", + "@wrnexus/mobile": "^0.8.5", + "@wrnexus/native": "^0.8.5", + "@wrnexus/oauth": "^0.8.5", + "@wrnexus/pubsub": "^0.8.5", + "@wrnexus/queue": "^0.8.5", + "@wrnexus/reactive": "^0.8.5", + "@wrnexus/router": "^0.8.5", + "@wrnexus/ssr": "^0.8.5", + "@wrnexus/styles": "^0.8.5", + "@wrnexus/test": "^0.8.5", + "@wrnexus/tracking": "^0.8.5", + "@wrnexus/ui": "^0.8.5", + "@wrnexus/uploader": "^0.8.5", + "@wrnexus/validation": "^0.8.5", + "@wrnexus/dev-toolbar": "^0.8.5", + "@wrnexus/syntax": "^0.8.5", + "@wrnexus/plugin": "^0.8.5", + "@wrnexus/captcha": "^0.8.5", + "@wrnexus/auth": "^0.8.5", + "@wrnexus/store": "^0.8.5", + "@wrnexus/typecheck": "^0.8.5", + "@wrnexus/security": "^0.8.5", + "@wrnexus/cache": "^0.8.5", + "@wrnexus/image": "^0.8.5", + "@wrnexus/observability": "^0.8.5", + "@wrnexus/benchmark": "^0.8.5", + "@wrnexus/realtime": "^0.8.5", + "@wrnexus/content": "^0.8.5", + "@wrnexus/graphql": "^0.8.5", + "@wrnexus/identity": "^0.8.5", + "@wrnexus/language-server": "^0.8.5", + "@wrnexus/mcp": "^0.8.5", + "@wrnexus/playground": "^0.8.5", + "@wrnexus/pwa": "^0.8.5", + "@wrnexus/rpc": "^0.8.5" }, "devDependencies": { "@eslint/js": "^9.0.0", "@tailwindcss/cli": "^4.0.0", "@types/bun": "latest", "@types/node": "^26.1.1", - "@wrnexus/cli": "^0.8.4", + "@wrnexus/cli": "^0.8.5", "eslint": "^9.0.0", "prettier": "latest", "tailwindcss": "^4.0.0", @@ -86,6 +87,6 @@ "typescript-eslint": "latest" }, "wrnexus": { - "version": "0.8.4" + "version": "0.8.5" } } diff --git a/public/docs-index.json b/public/docs-index.json index 20d4bd19..c7ecc162 100644 --- a/public/docs-index.json +++ b/public/docs-index.json @@ -1,5 +1,5 @@ { - "version": "0.8.4", + "version": "0.8.5", "status": "private-developer-preview", "generatedAt": "2026-07-13", "documents": [ @@ -7,616 +7,623 @@ "url": "/", "title": "WRNexusJS", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/access", "title": "access", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/getting-started", "title": "getting started", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/tutorial", "title": "tutorial", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/architecture", "title": "architecture", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/language", "title": "language", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages", "title": "packages", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/project-structure", "title": "project structure", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/routing", "title": "routing", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/pages-and-components", "title": "pages and components", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/server-data", "title": "server data", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/api-routes", "title": "api routes", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/middleware", "title": "middleware", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/forms-and-validation", "title": "forms and validation", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/authentication", "title": "authentication", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/authorization", "title": "authorization", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/security", "title": "security", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/database", "title": "database", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/uploads", "title": "uploads", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/realtime", "title": "realtime", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/pubsub", "title": "pubsub", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/queues", "title": "queues", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "experimental" }, { "url": "/guides/testing", "title": "testing", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/workspaces-and-gateway", "title": "workspaces and gateway", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/deployment", "title": "deployment", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/configuration-and-profiles", "title": "configuration and profiles", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/i18n-and-themes", "title": "i18n and themes", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/mobile", "title": "mobile", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "experimental" }, { "url": "/guides/observability", "title": "observability", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/upgrading", "title": "upgrading", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/guides/troubleshooting", "title": "troubleshooting", "section": "guide", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/examples", "title": "examples", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/showcase", "title": "showcase", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/benchmarks", "title": "benchmarks", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/roadmap", "title": "roadmap", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/changelog", "title": "changelog", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { - "url": "/releases/0.8.4", - "title": "0.8.4", + "url": "/releases/0.8.5", + "title": "0.8.5", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/security", "title": "security", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/support", "title": "support", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/license", "title": "license", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/search", "title": "search", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/404", "title": "404", "section": "portal", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/ai", "title": "ai", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/auth", "title": "auth", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/authz", "title": "authz", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/benchmark", "title": "benchmark", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/cache", "title": "cache", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/captcha", "title": "captcha", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/cli", "title": "cli", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/compiler", "title": "compiler", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/content", "title": "content", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/core", "title": "core", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/csr", "title": "csr", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/db", "title": "db", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/dev-server", "title": "dev server", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/dev-toolbar", "title": "dev toolbar", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/encryption", "title": "encryption", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/graphql", "title": "graphql", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/helpers", "title": "helpers", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/i18n", "title": "i18n", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/identity", "title": "identity", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/image", "title": "image", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/jwt", "title": "jwt", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/language-server", "title": "language server", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/mcp", "title": "mcp", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/mobile", "title": "mobile", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "experimental" }, { "url": "/packages/native", "title": "native", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/oauth", "title": "oauth", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/observability", "title": "observability", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/playground", "title": "playground", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/plugin", "title": "plugin", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/pubsub", "title": "pubsub", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/pwa", "title": "pwa", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/queue", "title": "queue", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/reactive", "title": "reactive", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/realtime", "title": "realtime", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/router", "title": "router", "section": "package", - "version": "0.8.4", + "version": "0.8.5", + "stability": "preview" + }, + { + "url": "/packages/rpc", + "title": "rpc", + "section": "package", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/security", "title": "security", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/ssr", "title": "ssr", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/store", "title": "store", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/styles", "title": "styles", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/syntax", "title": "syntax", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/test", "title": "test", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/tracking", "title": "tracking", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/typecheck", "title": "typecheck", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/ui", "title": "ui", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/uploader", "title": "uploader", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" }, { "url": "/packages/validation", "title": "validation", "section": "package", - "version": "0.8.4", + "version": "0.8.5", "stability": "preview" } ] diff --git a/public/llms-full.txt b/public/llms-full.txt index 696ae84b..4d323c0a 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -1,6 +1,6 @@ -# WRNexusJS documentation 0.8.4 +# WRNexusJS documentation 0.8.5 -Status: Private Developer Preview. This site documents 46 release-aligned packages. +Status: Private Developer Preview. This site documents 47 release-aligned packages. # WrNexus @@ -279,7 +279,7 @@ wrnexus eject # copy a Wire UI component's .wrn into app/compone 4. Style with Tailwind utility classes in the view, or theme tokens (`var(--wire-*)`), or `style { }`. 5. Never emit React/JSX, a manual router, or client-side island JS — the framework handles hydration. -Release: WRNexusJS 0.8.4 +Release: WRNexusJS 0.8.5 # Canonical documentation locations @@ -288,7 +288,7 @@ Release: WRNexusJS 0.8.4 # Installed package documentation -The following README files and declarations come from the installed private 0.8.4 release. +The following README files and declarations come from the installed private 0.8.5 release. ## @wrnexus/ai @@ -896,7 +896,7 @@ export { A as AUTH_SECURITY_EVENT_TYPES, a as AuthAccountStatus, b as AuthClock, export { MemoryAuthStore } from './stores/memory.js'; export { SqlAuthStore } from './stores/sql.js'; export { AUTH_SESSION_KEY, authSession, clearAuthSession, establishAuthSession, getAuthSession, getAuthUser, isAuthenticatedContext, requireAuth } from './middleware.js'; -export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-B4uaD0Z3.js'; +export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-BuZlwKSF.js'; export { AuthAuditIssue, AuthConfig, AuthPluginOptions, AuthRoutesConfig, authComponentsDir, authPlugin } from './plugin.js'; export { DefaultAuthRouteOptions, clearDefaultAuthEngine, getDefaultAuthEngine, getDefaultAuthRouteOptions, getDefaultAuthSchemas, hasDefaultAuthEngine, setDefaultAuthEngine, setDefaultAuthRouteOptions, setDefaultAuthSchemas, tryGetDefaultAuthEngine } from './runtime.js'; export { createAuthSecretProtector } from './protector.js'; @@ -1092,26 +1092,341 @@ app.put( - Works with [`@wrnexus/core`](../core) — the guards return `Middleware` and read the subject from `ctx.user` on the request `Context`. Both types are imported from `@wrnexus/core`. - Policy combinators (`any`, `all`) and `authorize` are async-aware, so policies may return a `Promise` (e.g. for a database ownership check). +## Declaring permissions + +The RBAC/PBAC/ABAC surface above is the low-level toolkit. On top of it sits a +declarative **registry + catalog + store + engine**: permissions, roles, and +policies are declared once in code, merged into a frozen catalog at boot, and +resolved per-request against a pluggable `PermissionStore` that holds who has +what. + +Put declarations in `app/authz/.ts`; they are discovered automatically +and merged (conflicting declarations of the same permission/role/policy across +files fail the boot loudly, naming both source files). + +```ts +import { defineAuthz, owner } from "@wrnexus/authz"; + +export default defineAuthz({ + permissions: { + "post:read": { title: "View posts", public: true }, + "post:delete": { title: "Delete posts", risk: "high" }, + }, + // "post:*" is a namespace wildcard grant, valid inside a role's list — it is + // not itself a registered permission, so it can only ever grant permissions + // that ARE declared above (e.g. "post:read", "post:delete"). + roles: { editor: ["post:*"], admin: ["role:editor"] }, + policies: { ownsPost: owner("id", "authorId") }, + bindings: { "post:delete": ["ownsPost"] }, +}); +``` + +`public: true` means anonymous callers may hold the permission — but any +policy bound to it still runs, and can still veto the anonymous caller (e.g. a +`notBanned` policy on a public `post:preview` permission). + +## Checking permissions + +Register `authzMiddleware` once, in `app/middleware/`, with the merged +catalog and a `PermissionStore`. Like every other `app/middleware/*.ts` file, +the registration is an eager, module-scope call — the same shape as +`authzMiddleware({ catalog, store })` requires — so it must run after the +catalog has been populated. Both the dev server and `wrnexus build`'s +generated production entry guarantee `getAuthzCatalog()` is populated before +any app middleware module evaluates. Name the file so it sorts after whatever +middleware sets `ctx.user` (middleware runs in alphabetical filename order — +`authz.ts` after `auth.ts`, for instance). + +```ts +// app/middleware/authz.ts +import { authzMiddleware, getAuthzCatalog } from "@wrnexus/authz"; +import { dbPermissionStore } from "@wrnexus/authz/db"; +import { getDb } from "@wrnexus/db"; + +export default authzMiddleware({ catalog: getAuthzCatalog(), store: dbPermissionStore(getDb()) }); +``` + +> **`subject.id` must be a non-empty string.** The engine denies (and logs to +> stderr) whenever `ctx.user.id` is present but not a non-empty string — this +> includes the common case of an integer primary key. Coerce it before it +> reaches `ctx.user`, e.g. `user.id = String(row.id)`, or every request for +> that user denies with "Invalid subject" instead of resolving normally. +> `owner()` (the built-in ownership policy) compares subject and resource ids +> with `Object.is`, so both sides must be the same type too — `owner()` on a +> numeric `resource.authorId` against a stringified `subject.id` never +> matches even when they represent "the same" id. + +There is no per-route `middleware` export — `app/middleware/*.ts` is the only +place middleware is registered. To gate part of the app, branch on the +request the same way any other conditional middleware does (compare +`app/middleware/captcha-login.ts` in the auth showcase, which branches on +method + path the same way): + +```ts +// app/middleware/protect-posts.ts +import type { Context, Next } from "@wrnexus/core"; +import { guardPermission } from "@wrnexus/authz"; + +const guardPostWrite = guardPermission("post:write"); + +export default function protectPosts(ctx: Context, next: Next) { + return ctx.url.pathname.startsWith("/api/posts") && ctx.req.method !== "GET" + ? guardPostWrite(ctx, next) + : next(); +} +``` + +Or check inline inside a route handler with the free function `can()`: + +```ts +// app/api/posts/[id].ts +import type { Context } from "@wrnexus/core"; +import { can } from "@wrnexus/authz"; + +export const DELETE = async (ctx: Context) => { + const post = { id: "1", authorId: "alice" }; // load your own resource here + if (!(await can(ctx, "post:delete", post))) { + return Response.json({ ok: false, error: "Forbidden" }, { status: 403 }); + } + return Response.json({ ok: true }); +}; +``` + +`can()` is a free function taking `ctx`, not `ctx.can` — `@wrnexus/core` must +not depend on `@wrnexus/authz`, so the per-request resolver lives in +`ctx.locals` instead, reached through `can()` / `decideFor()` / +`guardPermission()` / `filterCan()`. Calling any of them before +`authzMiddleware` has run for that request throws a `WRN-AUTHZ-SETUP` error +naming the missing registration, rather than silently denying. + +See `examples/auth-showcase/app/authz/showcase.ts` and +`examples/auth-showcase/app/middleware/authz.ts` for a complete, runnable +version of this wiring. + +## Precedence + +1. An explicit deny wins over everything, including `*` — and honours the + same namespace-wildcard matching as grants (denying `post:*` blocks + `post:comment:delete`, not just `post:*` itself). +2. A bound policy can veto a permission a role grants, and runs even for a + `public: true` permission — including for an anonymous caller. +3. Otherwise the permission must be held via a role or an explicit grant. +4. Default deny. + +Every failure — an unknown permission (outside strict/dev mode), a store +outage, a thrown policy — denies rather than throwing through to the caller. + +`permissionsFor()` (on the resolver returned by `createAuthzResolver`) is a +coarse hint for hiding UI (e.g. a menu section), **never authoritative**. A +`Set` cannot represent "granted `post:*` except `post:delete`", so a +narrow deny beneath a broad grant is invisible to it — the set still contains +`post:*` while `can()` / `decide()` correctly refuse `post:delete`. Gate real +actions with `can()`, `decideFor()`, or `filterCan()`; never by matching +against `permissionsFor()`'s result. + +## CLI + +```bash +wrnexus authz list # every registered permission, role, and policy +wrnexus authz generate # app/authz/permissions.gen.ts type unions +wrnexus authz init # scaffold the assignment-table migration +``` + +`wrnexus authz generate`'s output is a plain `Permission | Role` string-literal +union — `can()`, `guardPermission()`, and `decideFor()` all take a bare +`string` and nothing reads this file automatically, so import it to type your +own helpers/constants against the registered catalog, e.g.: + +```ts +import type { Permission } from "app/authz/permissions.gen.ts"; + +function guard(permission: Permission) { + return guardPermission(permission); +} +``` + ### Exported TypeScript declarations ```ts import { Context, Middleware } from '@wrnexus/core'; -interface AuthorizationDecision { +/** + * Validate and freeze one authorization declaration. Called from + * `app/authz/.ts` as the module's default export. + */ +declare function defineAuthz(module: AuthzModule): AuthzModule; + +interface CatalogSource { + /** File or package that declared this module, used in conflict messages. */ + source: string; + module: AuthzModule; +} +declare function emptyCatalog(): AuthzCatalog; +declare function mergeCatalogs(sources: CatalogSource[]): AuthzCatalog; + +/** + * A process-wide authorization catalog registry, mirroring `@wrnexus/db`'s + * `client.ts` (`setDb`/`getDb`/`hasDb`). It exists for the same reason: app + * middleware runs at module-eval time — `app/middleware/*.ts` registers + * `authzMiddleware({ catalog, store, ... })` itself, an EAGER call (the same + * shape as `logger.ts`'s `export default requestLogger({...})`), and it needs + * the merged catalog *then*, before its own module body finishes running. + * Passing it through `ctx` does not work at that point, so the framework + * loads and merges every `app/authz/*.ts` declaration and stashes it here + * before any other module can observe it: + * + * - dev: `startServer` calls `loadAppAuthzCatalog` + `setAuthzCatalog` + * before middleware is resolved. + * - prod (the normal `wrnexus build` output): the generated entry statically + * imports a small `.authz-setup.ts` module FIRST — before any page, API, + * or middleware import — which calls `setAuthzCatalog` at ITS OWN module + * scope. ES modules evaluate every static import before the importing + * module's body runs, and evaluate sibling imports in declaration order, + * so import position is evaluation order: this guarantees the catalog + * exists before app middleware's own module body (which may read it + * eagerly) ever evaluates. `createProductionHandlers` (`prod.ts`) then + * repeats the merge as an idempotent second pass, mainly so a caller who + * bypasses the generated entry and invokes it directly still gets a + * catalog — for THAT path specifically, an eager module-scope read in + * middleware is only safe if the caller sets the catalog before importing + * the middleware itself, since no generated `.authz-setup.ts` runs first. + * + * The framework never installs `authzMiddleware` itself — the app always + * chooses its own store and registers the middleware; this registry only + * makes the merged catalog reachable when it does. + */ + +/** Set the process-wide authorization catalog (called by the framework at boot). */ +declare function setAuthzCatalog(next: AuthzCatalog): AuthzCatalog; +/** The process-wide authorization catalog. Throws if it hasn't been set. */ +declare function getAuthzCatalog(): AuthzCatalog; +/** Whether the process-wide authorization catalog has been set. */ +declare function hasAuthzCatalog(): boolean; + +interface AuthzAuditEvent { + subjectId?: string; + scope?: AuthzScope; + permission: string; allowed: boolean; reason?: string; policy?: string; - metadata?: Record; + /** Epoch milliseconds. */ + at: number; } -type DecisionPolicy = (subject: S, resource?: R) => AuthorizationDecision | Promise; -declare function allow(reason?: string, metadata?: Record): AuthorizationDecision; -declare function deny(reason?: string, metadata?: Record): AuthorizationDecision; -declare function decision(name: string, policy: Policy, denial?: string): DecisionPolicy; -declare function owner>(subjectKey?: keyof SubjectType, resourceKey?: keyof Resource | string): DecisionPolicy; -declare function anyDecision(...policies: DecisionPolicy[]): DecisionPolicy; -declare function allDecisions(...policies: DecisionPolicy[]): DecisionPolicy; -declare function authorizeDecision(evaluate: (ctx: Context) => AuthorizationDecision | Promise): Middleware; -declare function filterAuthorized(subject: S, values: readonly R[], policy: Policy): Promise; +interface AuthzAuditSink { + record(event: AuthzAuditEvent): void | Promise; +} +interface MemoryAuditSink extends AuthzAuditSink { + events: AuthzAuditEvent[]; + clear(): void; +} +declare function memoryAuditSink(): MemoryAuditSink; +declare function consoleAuditSink(): AuthzAuditSink; +/** Record without ever letting a sink failure escape into the request path. */ +declare function safeRecord(sink: AuthzAuditSink | undefined, event: AuthzAuditEvent): void; + +interface AuthzResolverOptions { + catalog: AuthzCatalog; + store: PermissionStore; + audit?: AuthzAuditSink; + /** + * Throw on an unregistered permission instead of denying. Defaults to true + * outside production, so typos surface during development. + */ + strict?: boolean; + /** Record allows as well as denies. Off by default to bound write volume. */ + auditAllows?: boolean; +} +interface DecideInput { + subject: { + id?: string; + [key: string]: unknown; + } | null | undefined; + permission: string; + resource?: unknown; + scope?: AuthzScope; +} +interface AuthzResolver { + /** + * Effective permissions with denied entries removed — for coarse gating such + * as hiding a menu section. + * + * NOT authoritative. A set of strings cannot express "everything under + * `post:*` except `post:delete`", so a narrow deny beneath a broad grant is + * not representable here: the set still contains `post:*` while `decide()` + * correctly refuses `post:delete`. Gate individual actions with `decide()` + * (or `can()` / `filterCan()`), never by matching against this set. + */ + permissionsFor(subjectId: string, scope?: AuthzScope): Promise>; + decide(input: DecideInput): Promise; +} +/** Expand roles into their granted entries, following `role:` and stopping on cycles. */ +declare function expandRoles(catalog: AuthzCatalog, roles: readonly string[]): Set; +/** + * Exact match, root wildcard, or a namespace wildcard at any depth. + * + * Do NOT gate access by matching against `permissionsFor()`'s result — that set + * cannot represent a narrow deny beneath a broad grant, so the composition + * returns true where `decide()` refuses. Use `decide()` / `can()` instead. + */ +declare function permissionMatches(granted: Set, permission: string): boolean; +/** + * True if any entry in the deny list covers `permission`. Denies honour the + * same depth-aware wildcards as grants, so denying "post:*" blocks + * post:comment:delete rather than being accepted and silently doing nothing. + */ +declare function deniedBy(denies: readonly string[], permission: string): boolean; +declare function createAuthzResolver(options: AuthzResolverOptions): AuthzResolver; + +/** + * `can` is deliberately not a Context member: @wrnexus/core must not depend on + * @wrnexus/authz. The per-request resolver lives here instead. + */ +declare const AUTHZ_LOCALS_KEY = "_authz"; +/** Install the per-request resolver. Register early, after sessionAuth. */ +declare function authzMiddleware(options: AuthzResolverOptions): Middleware; +/** + * Object resources are memoised by identity (`byRef`), never by serialising + * their contents — serialisation is what let unrelated resources collide + * (same `id` shape, circular references, BigInt fields, throwing getters all + * funnelled into one bucket). Symbols are memoised by identity too (`bySymbol`) + * since `String(symbol)` collapses distinct symbols with the same description. + * Primitive/absent resources are memoised by a + * `[scope, permission, typeof, String(value)]` tuple, with `-0` rendered + * distinctly from `0` since `String(-0) === "0"` would otherwise merge them. + * + * Subject and scope are both part of the key. A request that reassigns + * ctx.user (impersonation, step-up auth, session revocation) or ctx.tenant + * must not be served the previous principal's verdict from the memo. + */ +declare function decideFor(ctx: Context, permission: string, resource?: unknown): Promise; +declare function can(ctx: Context, permission: string, resource?: unknown): Promise; +interface GuardOptions { + /** Load the resource a bound policy needs. */ + getResource?: (ctx: Context) => unknown; + /** Include reason and policy name in the 403 body. Off by default. */ + exposeReason?: boolean; + /** Redirect page requests here instead of returning 403. Ignored for JSON/API requests and for any non-local target. */ + redirectTo?: string; +} +/** + * Guard a route on a registered permission. Named `guardPermission` because + * `requirePermission(rbac, permission)` already exists with a different shape. + */ +declare function guardPermission(permission: string, options?: GuardOptions): Middleware; +/** Keep only the items the current subject may act on. */ +declare function filterCan(ctx: Context, permission: string, items: readonly T[]): Promise; + +/** + * Emit `Permission`/`Role` string-literal unions from the registered catalog. + * + * This does NOT make `can(ctx, "post:wrtie")` a type error — `can()`, + * `guardPermission()`, and `decideFor()` all take a bare `string`, and + * nothing in the framework consumes this generated file automatically. + * Import the unions yourself to type your OWN helpers/constants, e.g. + * `const PERM: Permission = "post:write"` or a typed wrapper around `can()`. + */ +declare function generatePermissionTypes(catalog: AuthzCatalog): string; /** * @wrnexus/authz — authorization: role-based (RBAC), policy-based (PBAC), and @@ -1156,7 +1471,108 @@ declare function requireRole(...roles: string[]): Middleware; /** Guard requiring an RBAC permission. */ declare function requirePermission(rbac: Rbac, permission: string): Middleware; -export { type AuthorizationDecision, type DecisionPolicy, type Policy, type Rbac, type Subject, all, allDecisions, allow, any, anyDecision, attr, authorize, authorizeDecision, decision, defineRbac, deny, filterAuthorized, hasRole, owner, requirePermission, requireRole }; +interface AuthorizationDecision { + allowed: boolean; + reason?: string; + policy?: string; + metadata?: Record; +} +type DecisionPolicy = (subject: S, resource?: R) => AuthorizationDecision | Promise; +declare function allow(reason?: string, metadata?: Record): AuthorizationDecision; +declare function deny(reason?: string, metadata?: Record): AuthorizationDecision; +declare function decision(name: string, policy: Policy, denial?: string): DecisionPolicy; +declare function owner>(subjectKey?: keyof SubjectType, resourceKey?: keyof Resource | string): DecisionPolicy; +declare function anyDecision(...policies: DecisionPolicy[]): DecisionPolicy; +declare function allDecisions(...policies: DecisionPolicy[]): DecisionPolicy; +interface AuthorizeDecisionOptions { + /** + * Include `reason` and `policy` in the 403 body. Off by default: policy + * names describe internal authorization structure and should not reach an + * unauthenticated caller. + */ + exposeReason?: boolean; +} +declare function authorizeDecision(evaluate: (ctx: Context) => AuthorizationDecision | Promise, options?: AuthorizeDecisionOptions): Middleware; +declare function filterAuthorized(subject: S, values: readonly R[], policy: Policy): Promise; + +/** Narrows an assignment to a tenant. Absent means a global assignment. */ +interface AuthzScope { + tenantId?: string; +} +interface PermissionMeta { + title?: string; + description?: string; + risk?: "low" | "medium" | "high"; + /** Granted to anonymous subjects. Every other permission denies without a user. */ + public?: boolean; +} +interface AttributeMeta { + description?: string; +} +/** One `app/authz/.ts` declaration. */ +interface AuthzModule { + permissions?: Record; + roles?: Record; + policies?: Record>; + attributes?: Record; + /** permission id -> policy names that must pass for it. */ + bindings?: Record; +} +/** The merged, frozen view of every declaration in the app. */ +interface AuthzCatalog { + permissions: ReadonlyMap; + roles: ReadonlyMap; + policies: ReadonlyMap>; + attributes: ReadonlyMap; + bindings: ReadonlyMap; +} +interface SubjectAssignments { + roles: string[]; + /** Explicit allows, bypassing roles. */ + grants: string[]; + /** Explicit denies. Win over everything, including "*". */ + denies: string[]; +} + +type GrantEffect = "allow" | "deny"; +interface PermissionStore { + assignmentsFor(subjectId: string, scope?: AuthzScope): Promise; + assignRole(subjectId: string, role: string, scope?: AuthzScope): Promise; + revokeRole(subjectId: string, role: string, scope?: AuthzScope): Promise; + grant(subjectId: string, permission: string, effect: GrantEffect, scope?: AuthzScope): Promise; + revokeGrant(subjectId: string, permission: string, scope?: AuthzScope): Promise; + listSubjects(scope?: AuthzScope): Promise; +} +/** + * Global assignments are stored under the empty-string scope key. An OMITTED + * scope means global; an explicitly EMPTY or non-string tenantId is refused, + * because an empty string is indistinguishable from global (and would let a + * caller who controls the tenant id read and write global assignments), and a + * non-string value (e.g. `null` from a JSON body or a nullable column) would + * otherwise flow through un-normalised and leave the adapters disagreeing + * about what happened. + */ +declare function scopeKey(scope?: AuthzScope): string; +declare function memoryPermissionStore(): PermissionStore; +interface CachedPermissionStore extends PermissionStore { + /** Drop one subject. Call after changing roles out of band. */ + invalidate(subjectId: string, scope?: AuthzScope): void; + invalidateAll(): void; + /** Cached entry count, for tests and diagnostics. */ + size(): number; +} +interface CacheOptions { + ttlMs?: number; + max?: number; +} +/** + * Caches assignment reads. Writes through this decorator invalidate the + * affected subject immediately; changes made directly against the inner store + * need an explicit `invalidate()` call rather than waiting out the TTL. + */ +declare function cachedPermissionStore(inner: PermissionStore, options?: CacheOptions): CachedPermissionStore; + +export { AUTHZ_LOCALS_KEY, type AttributeMeta, type AuthorizationDecision, type AuthorizeDecisionOptions, type AuthzAuditEvent, type AuthzAuditSink, type AuthzCatalog, type AuthzModule, type AuthzResolver, type AuthzResolverOptions, type AuthzScope, type CacheOptions, type CachedPermissionStore, type CatalogSource, type DecideInput, type DecisionPolicy, type GrantEffect, type GuardOptions, type MemoryAuditSink, type PermissionMeta, type PermissionStore, type Policy, type Rbac, type Subject, type SubjectAssignments, all, allDecisions, allow, any, anyDecision, attr, authorize, authorizeDecision, authzMiddleware, cachedPermissionStore, can, consoleAuditSink, createAuthzResolver, decideFor, decision, defineAuthz, defineRbac, deniedBy, deny, emptyCatalog, expandRoles, filterAuthorized, filterCan, generatePermissionTypes, getAuthzCatalog, guardPermission, hasAuthzCatalog, hasRole, memoryAuditSink, memoryPermissionStore, mergeCatalogs, owner, permissionMatches, requirePermission, requireRole, safeRecord, scopeKey, setAuthzCatalog }; ``` --- @@ -5847,6 +6263,7 @@ import { DevToolbarConfig, DevToolbarPlatformSnapshot, DevToolbarPanel } from '@ import { ClientRuntimeDefinition, PluginInput } from '@wrnexus/plugin'; import { CacheCoordinator } from '@wrnexus/cache'; import { DevToolbarCollector } from '@wrnexus/dev-toolbar/server'; +import { AuthzModule } from '@wrnexus/authz'; import { IncomingMessage, ServerResponse, Server } from 'node:http'; /** Exit code a dev-server child uses to request a clean supervisor restart. */ @@ -6185,6 +6602,11 @@ interface ProdManifest { name: string; mod: RouteModule; }[]; + /** RPC service implementations (from app/services/*.ts). */ + services?: { + name: string; + mod: RouteModule; + }[]; } interface ProductionPluginAsset { path: string; @@ -6214,6 +6636,19 @@ interface ProdOptions { frameworkCssPath?: string; /** Pre-built `window.__wireSchemas = {...}` script for client validation. */ schemasJs?: string; + /** + * Authorization declarations discovered by `wrnexus build` from + * `app/authz/*.ts`, statically imported into the generated entry (the + * catalog holds policy FUNCTIONS, so — unlike `schemasJs` — it cannot be + * JSON-serialised). `module` is `undefined` for a file with no default + * export. In the NORMAL generated-entry build, the catalog is already set + * by the generated `.authz-setup.ts` module before this ever runs (see + * `applyAuthzManifestEarly` below); `createProductionHandlers` merges this + * same list again as an idempotent second pass — with its warnings — so a + * caller that bypasses the generated entry and calls it directly still gets + * a correctly merged catalog. + */ + authz?: AuthzManifestEntry[]; /** Resolved i18n bundle (default lang + locale messages). */ i18n?: ResolvedI18n; /** Default database connection (driver + url); enables `getDb()`. */ @@ -6278,6 +6713,28 @@ interface ProdOptions { /** Enable only for the CLI's supervised exact-production development mode. */ developmentRuntime?: boolean; } +/** One `app/authz/*.ts` declaration as passed through `ProdOptions.authz`. */ +interface AuthzManifestEntry { + source: string; + /** Undefined when the declaration file has no default export. */ + module?: AuthzModule; +} +/** + * Merge + `setAuthzCatalog` as EARLY as possible, deliberately silently (no + * missing-default-export warnings). Called ONLY from the generated + * `.authz-setup.ts` module that `wrnexus build` imports FIRST in the + * production entry — before any other static import, including app + * middleware — so that a middleware module reading `getAuthzCatalog()` at its + * own module scope (the same eager shape `authzMiddleware({ catalog, ... })` + * itself requires) sees a populated catalog. `createProductionHandlers` below + * performs the exact same merge again, WITH its warnings, as the canonical, + * always-warns second pass — this function stays silent specifically so the + * normal boot path does not print the same "no default export" warning + * twice. A genuine conflict still throws here (via `mergeCatalogs`), which + * fails the boot at import time — before the entry body, and thus + * `createProductionHandlers`, ever runs. + */ +declare function applyAuthzManifestEarly(entries: AuthzManifestEntry[]): void; /** * Build the portable request handler from a precompiled manifest — a * WinterCG-style `fetch(request) => Response` plus the websocket handlers, with @@ -6388,7 +6845,7 @@ interface RunningServer { } declare function startServer(opts: ServeOptions): Promise; -export { type AssetServer, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WrnCompileMetrics, type WsData, createHandlers, createProductionHandlers, createProductionServer, expandStaticComponents, getWrnCompileMetrics, nodeListener, precomputePartialStaticShell, resetWrnCompileMetrics, serveNode, startGateway, startServer, toRequest, writeResponse }; +export { type AssetServer, type AuthzManifestEntry, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WrnCompileMetrics, type WsData, applyAuthzManifestEarly, createHandlers, createProductionHandlers, createProductionServer, expandStaticComponents, getWrnCompileMetrics, nodeListener, precomputePartialStaticShell, resetWrnCompileMetrics, serveNode, startGateway, startServer, toRequest, writeResponse }; ``` --- @@ -10716,6 +11173,10 @@ interface Router { stores: ComponentRef[]; /** Validation schemas (`app/schemas/.ts`) shared by API + forms. */ schemas: ComponentRef[]; + /** Authorization declarations (`app/authz/.ts`) merged into the catalog. */ + authz: ComponentRef[]; + /** Service implementations (`app/services/.ts`) mounted for inter-app calls. */ + services: ComponentRef[]; matchPage(pathname: string): RouteMatch | null; matchApi(pathname: string): RouteMatch | null; matchRealtime(pathname: string): RouteMatch | null; @@ -10752,6 +11213,339 @@ export { type ComponentRef, type ExternalRouteDefinition, type NamedRoute, type --- +## @wrnexus/rpc + +Documentation URL: https://wrnexusjs.dev/packages/rpc + +# `@wrnexus/rpc` + +Define a service contract in a shared workspace package, then import that same contract from the caller and callee. + +```ts +import { + defineService, + implement, + inProcessTransport, + procedure, + serviceClient, +} from "@wrnexus/rpc"; +import { v } from "@wrnexus/validation"; + +const greeter = defineService({ + name: "greeter", + procedures: { + greet: procedure + .input(v.object({ name: v.string() })) + .output<{ message: string }>() + .build(), + }, +}); + +const service = implement( + greeter, + { greet: async ({ name }) => ({ message: `Hello, ${name}` }) }, + { selfApp: "greeter" }, +); + +const client = serviceClient(greeter, { + app: "greeter", + transport: inProcessTransport({ + "greeter/greet": (input, identity) => service.invoke("greet", input, identity), + }), +}); +await client.greet({ name: "Ada" }); +``` + +Service files default-export `implement(...)` from `app/services`. The development server mounts them under the private `/__wrnexus/rpc` prefix. + +Pass `{ as: ctx }` to `serviceClient` to propagate the subject. The signed token contains only subject and tenant identifiers; permissions are always checked by the callee. Set `WRNEXUS_RPC_SECRET` in every app, use at least 32 characters, and never reuse the session secret. + +Calls time out by default. Retrying is intentionally deferred; when introduced, only procedures marked `.idempotent()` may be retried. + +## Deployment requirement: apps must be unreachable except through the gateway + +`/__wrnexus/rpc/*` is authenticated by TWO signals together: a marker header +(`x-wrnexus-internal: 1`) AND the absence of any `X-Forwarded-*` header. The +WrNexus gateway satisfies this by construction — it strips any inbound +marker header from the public request, and it always adds `X-Forwarded-*` +when proxying to an app. A direct loopback call from a sibling app process +carries the marker and no forwarded headers, so it passes; anything that +came through the gateway carries forwarded headers, so it's rejected even if +it also carries the marker. + +**This check only works if the app process is unreachable except through the +gateway.** If an app's port is exposed directly, or if a reverse proxy sits +in front of it WITHOUT setting `X-Forwarded-*` (a bare `proxy_pass` with no +`proxy_set_header X-Forwarded-For`/`X-Forwarded-Host`/`X-Forwarded-Proto`), +then an external caller can set the marker header itself, arrive with no +forwarded headers, and reach `/__wrnexus/rpc/*` as if it were an internal +call — bypassing the gateway's edge block entirely. + +Requirements for any deployment: + +- App processes must bind to a private/loopback interface and be reachable + ONLY through the gateway (or an equivalent trusted front door) — never + exposed directly to the internet or an untrusted network. +- Any reverse proxy placed in front of an app (nginx, a load balancer, etc.) + MUST set `X-Forwarded-For`, `X-Forwarded-Host`, and `X-Forwarded-Proto` on + every request it forwards. Omitting these silently reopens the private RPC + namespace to anyone who can reach the proxy. + +### Exported TypeScript declarations + +```ts +import { ObjectSchema } from '@wrnexus/validation'; +import { Context } from '@wrnexus/core'; + +/** Extract the validated value type from a `v.object(...)` schema. */ +type InferInput = S extends ObjectSchema ? T : never; +/** + * One callable procedure on a service. `input` is validated on the callee + * before the handler runs; `permission` is enforced there too. + */ +/** Structural shape of a validation schema, so ProcedureDef needs no generic. */ +interface InputSchema { + parse(value: Record): { + ok: boolean; + value: unknown; + errors: Record; + }; +} +interface ProcedureDef { + input?: InputSchema; + /** Permission the callee checks before invoking the handler. */ + permission?: string; + /** Only idempotent procedures are ever retried. */ + idempotent?: boolean; + /** Type-only markers; never present at runtime. */ + readonly __input?: Input; + readonly __output?: Output; +} +/** + * A procedure map with its element types erased. The `any` is deliberate and + * confined to this alias: the phantom `__input`/`__output` markers make + * ProcedureDef invariant, so no narrower erasure accepts a real contract. + * (No eslint-disable needed — `no-explicit-any` is off repo-wide, and a + * redundant directive is itself a lint warning.) + */ +type AnyProcedures = Record>; +interface ServiceContract { + /** Stable service id, used in the mounted path. */ + name: string; + procedures: Procedures; +} +type InferProcedureInput

    = P extends ProcedureDef ? I : never; +type InferProcedureOutput

    = P extends ProcedureDef ? O : never; +/** What a transport returns: either a value or a structured failure. */ +type ServiceResult = { + ok: true; + value: T; +} | { + ok: false; + code: string; + message: string; + retryable: boolean; +}; + +declare const RPC_ERROR_CODES: { + /** The request never reached a handler: connection, timeout, 5xx. */ + readonly transport: "RPC_TRANSPORT"; + /** Input failed the contract's schema. */ + readonly invalid: "RPC_INVALID"; + /** The callee's permission check refused. */ + readonly denied: "RPC_DENIED"; + /** No such service or procedure on the callee. */ + readonly unknown: "RPC_UNKNOWN"; + /** The handler threw or returned a failure. */ + readonly handler: "RPC_HANDLER"; + /** Identity token missing, malformed, expired, or for another audience. */ + readonly identity: "RPC_IDENTITY"; + /** + * The callee answered, but not with a ServiceResult — a proxy's HTML error + * page, a truncated body, an unexpected shape. Distinct from `transport`: + * something DID respond, so retrying returns the same thing. + */ + readonly malformed: "RPC_MALFORMED"; +}; +type RpcErrorCode = (typeof RPC_ERROR_CODES)[keyof typeof RPC_ERROR_CODES]; +/** + * 5xx, 429 and 408 mean "the callee could not answer, try later". Any other + * 4xx is the callee saying no — retrying just repeats the same rejection. + * + * The range is bounded on BOTH sides deliberately: an unbounded `>= 500` + * puts a garbage status like 1000 in the retryable bucket, and this function + * is the sole gate the client and HTTP transport trust for retry safety. + * An out-of-range value must fail closed, i.e. not retryable. + */ +declare function isRetryableStatus(status: number): boolean; +declare function success(value: T): ServiceResult; +declare function failure(code: string, message: string): ServiceResult; +interface ToResultOptions { + /** Include the original message. Off by default: it may name internals. */ + exposeMessage?: boolean; +} +declare class ServiceError extends Error { + readonly code: string; + readonly retryable: boolean; + /** + * `retryable` defaults to the code-derived value for callers that + * construct a `ServiceError` directly. Pass it explicitly when relaying a + * wire result: the transport already computed the authoritative value + * (e.g. a bounded HTTP-status check), and recomputing it here from the + * code alone would silently flip it — `RPC_TRANSPORT` derives to `true`, + * even for a non-retryable 403. + */ + constructor(code: string, message: string, retryable?: boolean); + /** + * Convert to a wire result. The message is replaced unless explicitly + * exposed: a handler's error text routinely names tables, hosts, or + * credentials, and this value crosses an app boundary. + */ + toResult(options?: ToResultOptions): ServiceResult; +} + +/** + * Fluent, IMMUTABLE builder: every method returns a new builder, so a shared + * base can be branched without one branch mutating another. + */ +declare class ProcedureBuilder { + private readonly def; + private constructor(); + static create(): ProcedureBuilder; + input>(schema: S): ProcedureBuilder, Output>; + output(): ProcedureBuilder; + permission(id: string): ProcedureBuilder; + /** Mark safe to retry. Anything not marked is never retried. */ + idempotent(): ProcedureBuilder; + build(): ProcedureDef; +} +declare const procedure: ProcedureBuilder; +declare function defineService(def: { + name: string; + procedures: Procedures; +}): ServiceContract; + +/** Header the identity token travels in. */ +declare const RPC_IDENTITY_HEADER = "x-wrnexus-rpc-identity"; +interface SubjectContext { + subjectId: string; + tenantId?: string; + /** + * The app that CLAIMS to have minted the token. Self-asserted: the signing + * secret is workspace-wide, so any app can set this to any name. Useful for + * logs and tracing; NEVER an authorization input. + */ + callerApp: string; +} +interface ExportOptions { + ttlSeconds?: number; +} +interface ImportOptions { + /** + * Reject a token older than this regardless of its own `exp`, so a caller + * that mints with a huge ttlSeconds cannot create a long-lived + * impersonation credential the callee will honour. Defaults to 300s. + */ + maxAgeSeconds?: number; +} +/** + * The workspace-wide RPC signing secret. + * + * Deliberately separate from the session secret: reusing that would make a + * leaked RPC token a session-forgery primitive. All workspace apps share this + * secret, so they form ONE trust boundary — any app can mint a token naming + * any user, and compromising the lowest-privilege app compromises identity + * across all of them. + */ +declare function rpcSecret(): string; +/** + * Mint a short-lived token naming the current subject, addressed to one app. + * + * Carries `sub` and `tenant` ONLY. Roles are deliberately absent: every app + * shares the PermissionStore, so the callee resolves them itself, which makes + * a stale or forged privilege claim impossible by construction. + * + * Returns undefined for an anonymous request — there is no identity to carry. + */ +declare function exportSubjectContext(ctx: Context, targetApp: string, options?: ExportOptions): Promise; +/** + * Verify a token addressed to THIS app and return the subject it names. + * + * `selfApp` is the audience check: it is what stops app B replaying a token it + * received from A against a third app C. + */ +declare function importSubjectContext(token: string, selfApp: string, options?: ImportOptions): Promise; + +interface RpcTarget { + app: string; + service: string; + procedure: string; +} +interface CallOptions { + signal?: AbortSignal; + identity?: string; +} +interface Transport { + call(target: RpcTarget, payload: unknown, options: CallOptions): Promise; +} +type InProcessHandler = (payload: unknown, identity?: string) => Promise | ServiceResult; +/** Direct transport for tests and local integration harnesses. */ +declare function inProcessTransport(handlers: Record): Transport; + +interface HandlerContext { + subject?: SubjectContext; +} +type ServiceHandlers = { + [K in keyof Procedures]: (input: InferProcedureInput, ctx: HandlerContext) => Promise> | InferProcedureOutput; +}; +interface ImplementOptions { + selfApp: string; + checkPermission?: (permission: string, subject?: SubjectContext) => Promise | boolean; +} +interface ServiceImplementation { + contract: ServiceContract; + invoke(procedure: string, payload: unknown, identity?: string): Promise; +} +declare function implement(contract: ServiceContract, handlers: ServiceHandlers, options: ImplementOptions): ServiceImplementation; + +interface ServiceClientOptions { + app?: string; + transport: Transport; + as?: Context; + timeoutMs?: number; +} +type ServiceClient = { + [K in keyof Procedures]: (input: InferProcedureInput) => Promise>; +}; +declare function serviceClient(contract: ServiceContract, options: ServiceClientOptions): ServiceClient; + +declare const RPC_PATH_PREFIX = "/__wrnexus/rpc"; +declare const RPC_INTERNAL_HEADER = "x-wrnexus-internal"; +declare function rpcPath(service: string, procedure: string): string; +/** + * Resolve the origin an RPC call to `app` should target. + * + * Prefer `WRNEXUS_INTERNAL_ORIGINS` (loopback origins the gateway hands each + * child before spawning it) over `appOrigin`, which resolves the app's + * PUBLIC origin. The public origin is the wrong target for RPC: the gateway + * unconditionally 404s the reserved `/__wrnexus/rpc` prefix on anything that + * arrives at a public origin — that block is the whole point, it is what + * keeps inter-app calls off the public internet. Falling back to `appOrigin` + * when no internal-origin map is present keeps single-app and test setups + * (which only set `WRNEXUS_WORKSPACE_ORIGINS`) working. + */ +declare function resolveAppOrigin(app: string): string; +interface HttpTransportOptions { + resolveOrigin?: (app: string) => string; + fetch?: typeof fetch; +} +declare function httpTransport(options?: HttpTransportOptions): Transport; + +export { type AnyProcedures, type CallOptions, type ExportOptions, type HandlerContext, type HttpTransportOptions, type ImplementOptions, type ImportOptions, type InProcessHandler, type InferInput, type InferProcedureInput, type InferProcedureOutput, type InputSchema, ProcedureBuilder, type ProcedureDef, RPC_ERROR_CODES, RPC_IDENTITY_HEADER, RPC_INTERNAL_HEADER, RPC_PATH_PREFIX, type RpcErrorCode, type RpcTarget, type ServiceClient, type ServiceClientOptions, type ServiceContract, ServiceError, type ServiceHandlers, type ServiceImplementation, type ServiceResult, type SubjectContext, type ToResultOptions, type Transport, defineService, exportSubjectContext, failure, httpTransport, implement, importSubjectContext, inProcessTransport, isRetryableStatus, procedure, resolveAppOrigin, rpcPath, rpcSecret, serviceClient, success }; +``` + +--- + ## @wrnexus/security Documentation URL: https://wrnexusjs.dev/packages/security @@ -10771,7 +11565,7 @@ setSecureCookie(ctx, "__Host-session", sessionId); ### Exported TypeScript declarations ```ts -export { S as SafeFetchOptions, a as SafeUrlPolicy, i as isPrivateAddress, b as isSafeUrl, s as safeFetch, c as sanitizeUrl, v as validateUrl } from './fetch-DNyX0J_D.js'; +export { S as SafeFetchOptions, a as SafeUrlPolicy, i as isPrivateAddress, b as isSafeUrl, s as safeFetch, c as sanitizeUrl, v as validateUrl } from './fetch-DzQ8J9S2.js'; export { SecureSerializeOptions, secureJsonStringify, serializeForHtml } from './serialization.js'; import { CookieOptions, Context, RequestLimitsConfig, Middleware, SecurityConfig } from '@wrnexus/core'; export { TrustedHtmlPolicy, TrustedHtmlValue, createTrustedHtml, isTrustedHtml, unwrapTrustedHtml } from './trusted-html.js'; @@ -12881,55 +13675,7 @@ Ways to customize the components, in increasing order of power: ### Exported TypeScript declarations ```ts -interface UiComponentMetadata { - name: string; - mount: string; - category?: string; - purpose?: string; - props?: Array<{ - name: string; - default?: unknown; - }>; - events?: string[]; -} -interface UiComponentReference { - count: number; - components: UiComponentMetadata[]; -} -declare function uiComponentReference(): UiComponentReference; -declare function findUiComponent(name: string): UiComponentMetadata | undefined; -declare function auditUiComponents(): Array<{ - component: string; - issue: string; -}>; - -/** - * @wrnexus/ui — the Wire UI component library. - * - * Components are `.wrn` files under `components/`, auto-discovered by the - * framework (the router scans this directory in addition to the app's own - * `app/components`). Mount them in any page with `data-component=""`. - * Their styles live in a single themeable stylesheet, `ui.css`, served once at - * `/__wrnexus/ui.css` — every class uses `var(--wire-*)` theme tokens. - * - * Override, in increasing order of power: - * 1. theme tokens (change `--wire-color-primary`, etc.) - * 2. redefine a `.wire-*` class in your own CSS (loaded after ui.css) - * 3. pass a `class` prop (appended to the component root) - * 4. `wrnexus eject ` to copy the component into `app/components` and own it - */ -/** Absolute path to the directory of Wire UI component `.wrn` files. */ -declare function uiComponentsDir(): string; -/** Absolute path to the Wire UI stylesheet. */ -declare function uiCssPath(): string; -/** The Wire UI stylesheet contents (all `.wire-*` classes, themed via tokens). */ -declare function uiCss(): string; -/** Names declared by the bundled components, independent of filename casing. */ -declare function uiComponentNames(): string[]; -/** Absolute path to a bundled component by its declared component name. */ -declare function uiComponentPath(name: string): string; - -export { type UiComponentMetadata, type UiComponentReference, auditUiComponents, findUiComponent, uiComponentNames, uiComponentPath, uiComponentReference, uiComponentsDir, uiCss, uiCssPath }; +export { } ``` --- @@ -20242,8 +20988,12 @@ component ContextMenu { sourceEvent.preventDefault() } if (placement === "pointer" && sourceEvent) { - positionX = Math.max(12, Math.min(sourceEvent.clientX || 12, window.innerWidth - 340)) - positionY = Math.max(12, Math.min(sourceEvent.clientY || 12, window.innerHeight - 420)) + // Place the menu at the pointer and let the anchored clamp in the + // runtime pull it back on screen once it has been laid out and can + // actually be measured. Subtracting a guessed 340x420 here instead + // pushed every menu that was not that size away from the pointer. + positionX = Math.max(12, sourceEvent.clientX || 12) + positionY = Math.max(12, sourceEvent.clientY || 12) } visible = true output.open({ @@ -20358,6 +21108,7 @@ component ContextMenu {

    - } -} -``` - ---- - ## Tabs Showcase: https://component.wrnexusjs.dev/ @@ -33127,6 +35734,985 @@ component ToastNotifications { --- +## Toaster + +Showcase: https://component.wrnexusjs.dev/ +Mount: (legacy: data-component="Toaster") +Category: core +Purpose: Reusable toaster component. +Props: color: string = "info", size: string = "default", position: string = "bottom-right", duration: number = 4500, max: number = 4, pauseOnHover: boolean = true, showIcon: boolean = true, successIcon: string = "", dangerIcon: string = "", warningIcon: string = "", infoIcon: string = "", closable: boolean = true, showProgress: boolean = true, closeLabel: string = "Dismiss notification", class: string = "" +Slots: none +Events: show, dismiss, action + +### Complete .wrn source contract + +```wrn +// +// Toaster -- the notification host. Mount it once (usually in a layout) and +// raise notifications from anywhere with the runtime global: +// +// toast("Saved") +// toast.success("Invite sent to " + email) +// toast.error("Could not save", { title: "Network error", duration: 8000 }) +// toast({ message: "Uploading", tone: "info", duration: 0 }) // 0 = sticky +// +// Each tone ships a built-in icon tinted with that tone colour -- green for +// success, red for danger, amber for warning, blue for info. Swap in your own +// per toast, or per tone on the host: +// +// toast.success("Shipped", { icon: "icon-[lucide--rocket]" }) +// toast("Quiet one", { icon: false }) // suppress the icon +// +// // never show icons +// +// Actions run your own code. The handler is passed straight through, so it +// closes over whatever the calling function can see: +// +// toast("Note deleted", { +// actionLabel: "Undo", +// onAction: function () { restoreNote(id) } +// }) +// +// toast.warning("Two versions of this file", { +// actions: [ +// { label: "Keep mine", onClick: keepMine }, +// { label: "Use theirs", onClick: useTheirs, tone: "danger", dismiss: false } +// ] +// }) +// +// The toast dismisses itself after an action; pass dismiss: false on the +// action to keep it open (for a step that has to report back). At most two +// actions render -- see normalizeActions. A declarative @action on the tag +// still fires for every click, so a page can log or route centrally. +// +// IMPORTANT -- what a callback may do. It runs long after the function that +// created it returned, and a client function only flushes its state when its +// body ends, so assigning your own component state from inside a callback +// writes to a dead local and is lost. Calling toast(), fetch, navigation and +// anything else that is not a state assignment works normally. To change +// state, dispatch an event and handle it declaratively, which re-enters with +// live state: +// +// onAction: function () { +// window.dispatchEvent(new CustomEvent("app:undo-delete")) +// } +// ... +//
    +// +// An icon prop is a CSS class, never markup, so any icon system works +// (iconify, an icon font, your own sprite). NOTE the class has to appear in +// YOUR source for a scanner like Tailwind to emit it -- that is exactly why +// the defaults are inline SVG rather than classes from this package. +// +// The runtime never imports this component: toast() dispatches a +// `wrnexus:toast` window event and this listens for it, so an app can supply +// its own host by listening for the same event. +// +// NOTE: apostrophes are avoided in the style block on purpose -- the .wrn +// block scanner treats a quote as a string delimiter while counting braces, +// so a stray one breaks parsing of the whole component. +component Toaster { + outputs { + show(payload: { id: number; message: string; tone: string }) + dismiss(payload: { id: number; reason: string }) + action(payload: { id: number; sourceEvent: Event }) + } + + props { + // Default tone for toasts raised without one of their own. Every Wire UI + // component takes color and size; here they set the stack defaults. + color: string = "info" + // default | sm | lg -- controls toast width and density. + size: string = "default" + // top-left | top-center | top-right | bottom-left | bottom-center | bottom-right + position: string = "bottom-right" + // Auto-dismiss delay in ms. 0 keeps a toast until it is dismissed. + duration: number = 4500 + // Oldest toasts beyond this are retired as new ones arrive. + max: number = 4 + pauseOnHover: boolean = true + // Icons: a built-in glyph per tone, tinted with that tone colour. + // Override any of them with an icon class of your own (iconify, an icon + // font, whatever your app already uses) -- the built-in SVG is only a + // fallback so the component needs no icon dependency. Per toast: + // toast.success("Saved", { icon: "icon-[lucide--party-popper]" }) + // toast("Quiet", { icon: false }) // no icon on this one + showIcon: boolean = true + successIcon: string = "" + dangerIcon: string = "" + warningIcon: string = "" + infoIcon: string = "" + closable: boolean = true + showProgress: boolean = true + closeLabel: string = "Dismiss notification" + class: string = "" + } + + state toasts = [] + state sequence = 0 + // Timer bookkeeping, deliberately outside `toasts`: the view never reads + // this, so pausing and resuming rebuilds no DOM. See the note in functions. + state timers = {} + + functions { + // TIMER DESIGN -- read before changing. + // + // 1. No callback here touches state. A client function gets state as a + // local snapshot and flushes it back when the body returns, so a write + // from a setTimeout callback lands in a dead local and is lost; calling + // a peer function from one re-flushes the stale snapshot over live + // state. Timers therefore only dispatch a window event, and the + // declarative @window handlers re-enter with live state. + // + // 2. Timer bookkeeping lives in `timers`, NOT on the toast entries. + // The view renders `toasts` through data-for, so touching a toast + // object rebuilds every row -- which restarted each progress bar from + // zero and made the bar look permanently full. Hover has to be free of + // that: pausing must leave the DOM completely alone. `timers` is never + // read by the view, so writing it re-renders nothing. + // + // 3. Everything that DOES change `toasts` (add, dismiss, remove) returns + // untouched items by reference for the rows it is not changing, so the + // keyed loop reuses those nodes and their bars keep running. + client function scheduleEvent(name, id, delay) { + return setTimeout(function () { + window.dispatchEvent(new CustomEvent(name, { detail: { id: id } })) + }, delay) + } + + // kind is either "dismiss" (the toast lifetime, which hover pauses) or + // "remove" (the exit-animation cleanup, which hover must NOT touch -- + // see pauseAll). + client function trackTimer(id, handle, life, kind) { + var next = {} + Object.keys(timers).forEach(function (key) { next[key] = timers[key] }) + next[id] = { + handle: handle, + expiresAt: Date.now() + life, + remaining: life, + kind: kind || "dismiss" + } + timers = next + } + + client function forgetTimer(id) { + var next = {} + Object.keys(timers).forEach(function (key) { + if (String(key) !== String(id)) { + next[key] = timers[key] + } + }) + timers = next + } + + // An explicit per-toast icon wins; otherwise the tone default prop; and if + // that is empty the built-in SVG for the tone renders instead. Returns a + // CSS class name, never markup, so an app can hand us any icon system. + client function resolveIcon(tone, requested) { + if (requested) { + return String(requested) + } + if (tone === "success") { + return successIcon + } + if (tone === "danger") { + return dangerIcon + } + if (tone === "warning") { + return warningIcon + } + if (tone === "info") { + return infoIcon + } + return "" + } + + // Actions arrive either as a single actionLabel/onAction pair or as an + // actions array. At most two are rendered: the view has two fixed slots + // because a data-for inside a data-for is not expanded by the runtime, so + // an arbitrary list cannot be rendered per row. Two covers the real cases + // (Undo, Retry, View / Dismiss); anything beyond that is dropped loudly + // rather than silently. + client function normalizeActions(detail) { + var list = [] + if (Array.isArray(detail.actions)) { + list = detail.actions.filter(function (action) { return action && action.label }) + } else if (detail.actionLabel) { + list = [{ label: detail.actionLabel, onClick: detail.onAction, tone: detail.actionTone }] + } + if (list.length > 2) { + console.warn( + "[wrnexus] Toaster renders at most 2 actions per toast; ignoring " + + (list.length - 2) + " extra." + ) + } + return list.slice(0, 2) + } + + // Is the pointer resting on the stack right now? + // + // mouseenter only fires when the pointer MOVES. A toast raised while the + // cursor is already parked over the stack -- which is exactly what an + // action handler does -- therefore gets no enter event, is never paused, + // and counts down and disappears while the user is still reaching for its + // button. Its progress bar meanwhile IS paused, because CSS :hover does + // apply, so the bar sat still while the toast quietly expired. Asking the + // DOM for the live :hover state closes that gap. + client function stackHovered() { + var list = refs.list + return !!(pauseOnHover && list && list.matches(":hover")) + } + + client function receiveToast(sourceEvent) { + var detail = sourceEvent.detail || {} + + // One toast per raise, however many hosts are mounted. + // + // toast() dispatches a window event, so EVERY mounted Toaster hears it + // and a page with two hosts showed the message twice (the component + // showcase mounts five and showed five). Claiming the event on the + // detail object lets the first host win and the rest stand down, so an + // accidental second host is harmless instead of multiplying every + // notification. + if (detail.__wrnClaimed) { + return + } + detail.__wrnClaimed = true + sequence = sequence + 1 + + var id = sequence + var life = detail.duration === 0 ? 0 : (detail.duration || duration) + var tone = detail.tone || color + + var entry = { + id: id, + title: detail.title || "", + message: detail.message === undefined ? "" : String(detail.message), + tone: tone, + icon: resolveIcon(tone, detail.icon), + showIcon: showIcon && detail.icon !== false, + actions: normalizeActions(detail), + duration: life, + leaving: false + } + + // Retire the oldest live toasts in the same pass that appends the new + // one, so a burst can never leave the stack over max. Untouched rows are + // returned by reference so their nodes (and bars) survive. + var live = toasts.filter(function (item) { return !item.leaving }) + var retire = live.length + 1 > max ? live.slice(0, live.length + 1 - max) : [] + + toasts = toasts + .map(function (item) { + var doomed = retire.some(function (old) { return old.id === item.id }) + return doomed ? Object.assign({}, item, { leaving: true }) : item + }) + .concat([entry]) + + retire.forEach(function (item) { + clearTimeout((timers[item.id] || {}).handle) + trackTimer(item.id, scheduleEvent("wrnexus:toast:remove", item.id, 240), 240, "remove") + }) + + if (life) { + // Born paused when the stack is already hovered: handle 0 parks it, + // and resumeAll starts the clock when the pointer finally leaves. + if (stackHovered()) { + trackTimer(id, 0, life, "dismiss") + } else { + trackTimer(id, scheduleEvent("wrnexus:toast:dismiss", id, life), life, "dismiss") + } + } + output.show({ id: id, message: entry.message, tone: entry.tone }) + } + + client function dismissToast(id, reason) { + var found = false + toasts = toasts.map(function (item) { + if (item.id !== id || item.leaving) { + return item + } + found = true + return Object.assign({}, item, { leaving: true }) + }) + if (!found) { + return + } + clearTimeout((timers[id] || {}).handle) + // Give the exit animation time to play, then drop the entry. + trackTimer(id, scheduleEvent("wrnexus:toast:remove", id, 240), 240, "remove") + output.dismiss({ id: id, reason: reason || "auto" }) + } + + client function removeToast(id) { + clearTimeout((timers[id] || {}).handle) + forgetTimer(id) + toasts = toasts.filter(function (item) { return item.id !== id }) + } + + client function dismissById(sourceEvent) { + var detail = sourceEvent.detail || {} + dismissToast(detail.id, detail.reason || "timeout") + } + + client function removeById(sourceEvent) { + var detail = sourceEvent.detail || {} + removeToast(detail.id) + } + + client function clearAll() { + toasts.slice().forEach(function (item) { + if (!item.leaving) { + dismissToast(item.id, "clear") + } + }) + } + + // Hovering must not run the clock down while a toast is being read, so + // the remaining time is banked and the timers restart on the way out. + // Only `timers` is written, so not a single DOM node is rebuilt -- the + // progress bars simply stop where they are (CSS pauses them on :hover) + // and carry on from there. + client function pauseAll() { + if (!pauseOnHover) { + return + } + var now = Date.now() + var next = {} + Object.keys(timers).forEach(function (key) { + var entry = timers[key] + // A "remove" timer finishes an exit animation -- pausing it strands + // the toast: invisible, still taking up space in the stack, and still + // able to swallow clicks, forever. Only lifetimes pause. + if (!entry || !entry.handle || entry.kind !== "dismiss") { + next[key] = entry + return + } + clearTimeout(entry.handle) + var left = entry.expiresAt - now + next[key] = { + handle: 0, + expiresAt: entry.expiresAt, + remaining: left > 0 ? left : 1, + kind: "dismiss" + } + }) + timers = next + } + + client function resumeAll() { + if (!pauseOnHover) { + return + } + var now = Date.now() + var next = {} + Object.keys(timers).forEach(function (key) { + var entry = timers[key] + if (!entry || entry.handle || entry.kind !== "dismiss") { + next[key] = entry + return + } + var left = entry.remaining > 0 ? entry.remaining : 1 + // Number(key): object keys come back as strings, and the dismiss + // handler matches ids with !==, so a string id silently matches no + // toast and the resumed timer would fire into the void. + next[key] = { + handle: scheduleEvent("wrnexus:toast:dismiss", Number(key), left), + expiresAt: now + left, + remaining: left, + kind: "dismiss" + } + }) + timers = next + } + + // The click handler for an action. Runs as a fresh invocation from the + // DOM, so state here is live and calling peer functions is safe. + client function runAction(id, index, sourceEvent) { + var toast = null + toasts.forEach(function (item) { + if (item.id === id) { + toast = item + } + }) + if (!toast) { + return + } + + var action = toast.actions[index] + if (!action) { + return + } + + // Declarative listeners on the tag see every action too. + output.action({ + id: id, + index: index, + label: action.label, + sourceEvent: sourceEvent + }) + + // The callback is application code: a throw here must not take the + // toaster down with it, or the toast would be stuck on screen forever. + if (typeof action.onClick === "function") { + try { + action.onClick(sourceEvent) + } catch (error) { + console.error("[wrnexus] toast action handler failed", error) + } + } + + // NOTHING may call a peer function past this point. + // + // The callback is application code and is re-entrant: a handler that + // raises its own toast runs receiveToast in a fresh invocation, which + // appends to live state. Calling a peer from here would first flush the + // snapshot this function captured on entry -- taken BEFORE the callback + // ran -- straight over that live state, silently erasing the toast the + // handler just raised. So the dismissal is dispatched inline instead, + // and handled on the next tick with state that is actually current. + // This function never assigns to state itself, so it flushes nothing. + if (action.dismiss !== false) { + setTimeout(function () { + window.dispatchEvent( + new CustomEvent("wrnexus:toast:dismiss", { + detail: { id: id, reason: "action" } + }) + ) + }, 0) + } + } + } + + view { +
    + +
      +
    1. + + + + + + + + +
      +

      + {item.title} +

      +

      + {item.message} +

      +
      + + +
      + + + +
      + + + + + +
    2. +
    +
    + } + + style { + .wire-toaster { + position: fixed; + inset: 0; + z-index: 1400; + display: flex; + padding: clamp(0.75rem, 2vw, 1.25rem); + /* The host covers the viewport so it can align the stack in any corner; + it must never swallow clicks meant for the page underneath. */ + pointer-events: none; + } + + /* + * pointer-events MUST be re-enabled here, not only on .wire-toast. + * + * The host is pointer-events: none so the page underneath stays clickable + * through the empty overlay, and the list inherits that. An element with + * pointer-events: none is never a hit-test target, so it never matches + * :hover AND never receives mouseenter/mouseleave -- and those two do not + * bubble up from the rows either. The result was that hover-to-pause did + * nothing at all for a real user: toasts kept counting down and vanished + * from under the cursor as they reached for the action button. (Synthetic + * dispatchEvent bypasses hit-testing, so it hid this in testing.) + * + * The list box wraps the stack exactly -- its height is the toasts plus + * their gaps -- so making it interactive costs the page nothing. + */ + .wire-toaster__list { + display: flex; + flex-direction: column; + gap: 0.6rem; + width: min(23rem, 100%); + margin: 0; + padding: 0; + list-style: none; + pointer-events: auto; + } + + /* Nothing to hover when the stack is empty. */ + .wire-toaster__list:empty { + pointer-events: none; + } + + .wire-toaster[data-size="sm"] .wire-toaster__list { + width: min(18rem, 100%); + } + + .wire-toaster[data-size="lg"] .wire-toaster__list { + width: min(28rem, 100%); + } + + .wire-toaster[data-size="sm"] .wire-toast { + padding: 0.6rem 0.7rem; + font-size: 0.78rem; + } + + .wire-toaster[data-size="lg"] .wire-toast { + padding: 1.05rem 1.1rem; + } + + .wire-toaster[data-position^="top"] { + align-items: flex-start; + } + + .wire-toaster[data-position^="bottom"] { + align-items: flex-end; + } + + /* Newest nearest the screen edge: at the bottom that means visually last, + so the column is reversed rather than the state array. */ + .wire-toaster[data-position^="bottom"] .wire-toaster__list { + flex-direction: column-reverse; + } + + .wire-toaster[data-position$="left"] { + justify-content: flex-start; + } + + .wire-toaster[data-position$="center"] { + justify-content: center; + } + + .wire-toaster[data-position$="right"] { + justify-content: flex-end; + } + + .wire-toast { + position: relative; + display: flex; + align-items: flex-start; + gap: 0.7rem; + overflow: hidden; + padding: 0.85rem 0.9rem; + color: var(--wire-color-text); + background: var(--wire-color-surface-raised); + border: 1px solid var(--wire-color-border); + border-radius: 0.9rem; + box-shadow: 0 18px 40px color-mix(in srgb, black 28%, transparent); + pointer-events: auto; + animation: wire-toast-in 220ms cubic-bezier(0.16, 1, 0.3, 1) both; + } + + .wire-toaster[data-position$="left"] .wire-toast { + animation-name: wire-toast-in-left; + } + + /* + * Belt and braces: a toast on its way out is faded to nothing but still + * occupies its box until it is dropped from the list, so without this it + * can swallow clicks aimed at whatever is under it. + */ + .wire-toast[data-leaving="true"] { + animation: wire-toast-out 200ms ease forwards; + pointer-events: none; + } + + .wire-toast__indicator { + flex: 0 0 auto; + width: 0.4rem; + align-self: stretch; + border-radius: 999px; + background: var(--toast-accent, var(--wire-color-primary)); + } + + .wire-toast[data-tone="success"] { + --toast-accent: var(--wire-color-success); + } + + .wire-toast[data-tone="danger"] { + --toast-accent: var(--wire-color-danger); + } + + .wire-toast[data-tone="warning"] { + --toast-accent: var(--wire-color-warning); + } + + .wire-toast[data-tone="info"] { + --toast-accent: var(--wire-color-info); + } + + /* + * Centred like the trailing controls. The row is top-aligned so long text + * starts at the top, but on a one-line toast the 1.75rem close button is + * taller than the text, so a top-aligned body left the text sitting a few + * pixels above the button it is supposed to line up with. + */ + /* + * Tinted with the tone accent, so the glyph reads as the status at a + * glance -- green for success, red for danger, amber for warning, and the + * info colour otherwise. The built-in SVG strokes with currentColor, and + * an app icon class that uses currentColor (iconify does) picks up the + * same value for free. + */ + .wire-toast__icon { + flex: 0 0 auto; + align-self: center; + width: 1.15rem; + height: 1.15rem; + color: var(--toast-accent, var(--wire-color-primary)); + } + + .wire-toast__body { + flex: 1 1 auto; + min-width: 0; + align-self: center; + display: grid; + gap: 0.15rem; + } + + .wire-toast__title, + .wire-toast__message { + margin: 0; + overflow-wrap: anywhere; + } + + .wire-toast__title { + color: var(--wire-color-text); + font-size: 0.85rem; + font-weight: 650; + line-height: 1.35; + } + + .wire-toast__message { + color: var(--wire-color-text-muted); + font-size: 0.82rem; + line-height: 1.5; + } + + /* + * The trailing controls share one alignment. The close button used to be + * pinned to the top with a negative margin while the action sat centred, + * so the two sat on different lines and read as misaligned. Both are + * centred against the toast body now, and both are the same height, so + * their centres line up whether the toast is one line or three. + */ + .wire-toast__actions { + display: flex; + align-items: center; + flex: 0 0 auto; + align-self: center; + gap: 0.35rem; + } + + /* A destructive action reads in the danger colour regardless of tone. */ + .wire-toast__action[data-tone="danger"] { + color: var(--wire-color-danger); + border-color: color-mix(in srgb, var(--wire-color-danger) 45%, transparent); + } + + .wire-toast__action { + appearance: none; + flex: 0 0 auto; + min-height: 1.75rem; + display: inline-flex; + align-items: center; + padding: 0 0.6rem; + color: var(--toast-accent, var(--wire-color-primary)); + background: transparent; + border: 1px solid color-mix(in srgb, var(--toast-accent, var(--wire-color-primary)) 40%, transparent); + border-radius: 0.55rem; + font: inherit; + font-size: 0.78rem; + font-weight: 650; + cursor: pointer; + } + + /* + * padding is reset explicitly: an app-level button padding rule beats the + * browser default and collapses the icon to a sliver inside this + * fixed-size button. + */ + .wire-toast__close { + appearance: none; + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + align-self: center; + padding: 0; + width: 1.75rem; + height: 1.75rem; + margin: 0; + color: var(--wire-color-text-muted); + background: transparent; + border: 0; + border-radius: 999px; + cursor: pointer; + transition: color 150ms ease, background 150ms ease; + } + + .wire-toast__close:hover { + color: var(--wire-color-text); + background: var(--wire-color-surface-soft); + } + + .wire-toast__close svg { + flex: 0 0 auto; + width: 0.875rem; + height: 0.875rem; + } + + /* + * Sweeps left to right as the toast lives out its delay, reaching full + * width as it is dismissed, so the remaining time is readable at a glance. + * (Flip the keyframes below to run 1 -> 0 if you would rather it drain.) + */ + .wire-toast__progress { + position: absolute; + left: 0; + bottom: 0; + height: 2px; + width: 100%; + transform-origin: left center; + background: var(--toast-accent, var(--wire-color-primary)); + animation: wire-toast-progress var(--toast-duration, 4500ms) linear forwards; + } + + /* Hover pauses the clock, so the bar must pause with it or it would lie + about how much time is left. */ + /* + * Paused straight from :hover rather than from a state flag. A flag would + * mean writing state on every hover, and that rebuilds the rows -- which + * restarts the bars from zero and is exactly what made them look stuck. + * CSS pauses the animation in place and touches no DOM, and the JS timer + * is banked on the same mouseenter, so the two stay in step. + */ + .wire-toaster__list:hover .wire-toast__progress, + .wire-toaster__list:focus-within .wire-toast__progress { + animation-play-state: paused; + } + + @keyframes wire-toast-in { + from { + opacity: 0; + transform: translateX(18px) scale(0.98); + } + to { + opacity: 1; + transform: none; + } + } + + @keyframes wire-toast-in-left { + from { + opacity: 0; + transform: translateX(-18px) scale(0.98); + } + to { + opacity: 1; + transform: none; + } + } + + @keyframes wire-toast-out { + to { + opacity: 0; + transform: translateX(12px) scale(0.97); + } + } + + @keyframes wire-toast-progress { + from { + transform: scaleX(0); + } + to { + transform: scaleX(1); + } + } + + @media (max-width: 639px) { + .wire-toaster { + justify-content: stretch; + } + + .wire-toaster__list { + width: 100%; + } + } + + /* + * Reduced motion drops the entry/exit movement but KEEPS the progress + * sweep: it is a clock, not decoration, and a frozen bar would both + * misreport the time left and look like the bug it used to be. A linear + * 2px bar carries no vestibular risk. + */ + @media (prefers-reduced-motion: reduce) { + .wire-toast, + .wire-toast[data-leaving="true"] { + animation: none; + } + } + } +} +``` + +--- + ## ToggleCount Showcase: https://component.wrnexusjs.dev/ @@ -33729,11 +37315,12 @@ id: string = "" {#if showArrow} - + {/if} {#if title} diff --git a/public/llms.txt b/public/llms.txt index 6e0fb795..8f7eb8bc 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -1,6 +1,6 @@ -# WRNexusJS documentation 0.8.4 +# WRNexusJS documentation 0.8.5 -Status: Private Developer Preview. This site documents 46 release-aligned packages. +Status: Private Developer Preview. This site documents 47 release-aligned packages. # WrNexus @@ -289,283 +289,289 @@ wrnexus eject # copy a Wire UI component's .wrn into app/compone ## @wrnexus/ai -- @wrnexus/ai 0.8.4 +- @wrnexus/ai 0.8.5 - Documentation: https://wrnexusjs.dev/packages/ai - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/auth -- @wrnexus/auth 0.8.4 +- @wrnexus/auth 0.8.5 - Documentation: https://wrnexusjs.dev/packages/auth - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/authz -- @wrnexus/authz 0.8.4 +- @wrnexus/authz 0.8.5 - Documentation: https://wrnexusjs.dev/packages/authz - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/benchmark -- @wrnexus/benchmark 0.8.4 +- @wrnexus/benchmark 0.8.5 - Documentation: https://wrnexusjs.dev/packages/benchmark - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/cache -- @wrnexus/cache 0.8.4 +- @wrnexus/cache 0.8.5 - Documentation: https://wrnexusjs.dev/packages/cache - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/captcha -- @wrnexus/captcha 0.8.4 +- @wrnexus/captcha 0.8.5 - Documentation: https://wrnexusjs.dev/packages/captcha - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/cli -- @wrnexus/cli 0.8.4 +- @wrnexus/cli 0.8.5 - Documentation: https://wrnexusjs.dev/packages/cli - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/compiler -- @wrnexus/compiler 0.8.4 +- @wrnexus/compiler 0.8.5 - Documentation: https://wrnexusjs.dev/packages/compiler - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/content -- @wrnexus/content 0.8.4 +- @wrnexus/content 0.8.5 - Documentation: https://wrnexusjs.dev/packages/content - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/core -- @wrnexus/core 0.8.4 +- @wrnexus/core 0.8.5 - Documentation: https://wrnexusjs.dev/packages/core - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/csr -- @wrnexus/csr 0.8.4 +- @wrnexus/csr 0.8.5 - Documentation: https://wrnexusjs.dev/packages/csr - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/db -- @wrnexus/db 0.8.4 +- @wrnexus/db 0.8.5 - Documentation: https://wrnexusjs.dev/packages/db - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/dev-server -- @wrnexus/dev-server 0.8.4 +- @wrnexus/dev-server 0.8.5 - Documentation: https://wrnexusjs.dev/packages/dev-server - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/dev-toolbar -- @wrnexus/dev-toolbar 0.8.4 +- @wrnexus/dev-toolbar 0.8.5 - Documentation: https://wrnexusjs.dev/packages/dev-toolbar - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/encryption -- @wrnexus/encryption 0.8.4 +- @wrnexus/encryption 0.8.5 - Documentation: https://wrnexusjs.dev/packages/encryption - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/graphql -- @wrnexus/graphql 0.8.4 +- @wrnexus/graphql 0.8.5 - Documentation: https://wrnexusjs.dev/packages/graphql - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/helpers -- @wrnexus/helpers 0.8.4 +- @wrnexus/helpers 0.8.5 - Documentation: https://wrnexusjs.dev/packages/helpers - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/i18n -- @wrnexus/i18n 0.8.4 +- @wrnexus/i18n 0.8.5 - Documentation: https://wrnexusjs.dev/packages/i18n - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/identity -- @wrnexus/identity 0.8.4 +- @wrnexus/identity 0.8.5 - Documentation: https://wrnexusjs.dev/packages/identity - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/image -- @wrnexus/image 0.8.4 +- @wrnexus/image 0.8.5 - Documentation: https://wrnexusjs.dev/packages/image - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/jwt -- @wrnexus/jwt 0.8.4 +- @wrnexus/jwt 0.8.5 - Documentation: https://wrnexusjs.dev/packages/jwt - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/language-server -- @wrnexus/language-server 0.8.4 +- @wrnexus/language-server 0.8.5 - Documentation: https://wrnexusjs.dev/packages/language-server - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/mcp -- @wrnexus/mcp 0.8.4 +- @wrnexus/mcp 0.8.5 - Documentation: https://wrnexusjs.dev/packages/mcp - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/mobile -- @wrnexus/mobile 0.8.4 +- @wrnexus/mobile 0.8.5 - Documentation: https://wrnexusjs.dev/packages/mobile - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/native -- @wrnexus/native 0.8.4 +- @wrnexus/native 0.8.5 - Documentation: https://wrnexusjs.dev/packages/native - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/oauth -- @wrnexus/oauth 0.8.4 +- @wrnexus/oauth 0.8.5 - Documentation: https://wrnexusjs.dev/packages/oauth - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/observability -- @wrnexus/observability 0.8.4 +- @wrnexus/observability 0.8.5 - Documentation: https://wrnexusjs.dev/packages/observability - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/playground -- @wrnexus/playground 0.8.4 +- @wrnexus/playground 0.8.5 - Documentation: https://wrnexusjs.dev/packages/playground - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/plugin -- @wrnexus/plugin 0.8.4 +- @wrnexus/plugin 0.8.5 - Documentation: https://wrnexusjs.dev/packages/plugin - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/pubsub -- @wrnexus/pubsub 0.8.4 +- @wrnexus/pubsub 0.8.5 - Documentation: https://wrnexusjs.dev/packages/pubsub - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/pwa -- @wrnexus/pwa 0.8.4 +- @wrnexus/pwa 0.8.5 - Documentation: https://wrnexusjs.dev/packages/pwa - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/queue -- @wrnexus/queue 0.8.4 +- @wrnexus/queue 0.8.5 - Documentation: https://wrnexusjs.dev/packages/queue - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/reactive -- @wrnexus/reactive 0.8.4 +- @wrnexus/reactive 0.8.5 - Documentation: https://wrnexusjs.dev/packages/reactive - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/realtime -- @wrnexus/realtime 0.8.4 +- @wrnexus/realtime 0.8.5 - Documentation: https://wrnexusjs.dev/packages/realtime - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/router -- @wrnexus/router 0.8.4 +- @wrnexus/router 0.8.5 - Documentation: https://wrnexusjs.dev/packages/router - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt +## @wrnexus/rpc + +- @wrnexus/rpc 0.8.5 +- Documentation: https://wrnexusjs.dev/packages/rpc +- README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt + ## @wrnexus/security -- @wrnexus/security 0.8.4 +- @wrnexus/security 0.8.5 - Documentation: https://wrnexusjs.dev/packages/security - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/ssr -- @wrnexus/ssr 0.8.4 +- @wrnexus/ssr 0.8.5 - Documentation: https://wrnexusjs.dev/packages/ssr - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/store -- @wrnexus/store 0.8.4 +- @wrnexus/store 0.8.5 - Documentation: https://wrnexusjs.dev/packages/store - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/styles -- @wrnexus/styles 0.8.4 +- @wrnexus/styles 0.8.5 - Documentation: https://wrnexusjs.dev/packages/styles - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/syntax -- @wrnexus/syntax 0.8.4 +- @wrnexus/syntax 0.8.5 - Documentation: https://wrnexusjs.dev/packages/syntax - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/test -- @wrnexus/test 0.8.4 +- @wrnexus/test 0.8.5 - Documentation: https://wrnexusjs.dev/packages/test - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/tracking -- @wrnexus/tracking 0.8.4 +- @wrnexus/tracking 0.8.5 - Documentation: https://wrnexusjs.dev/packages/tracking - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/typecheck -- @wrnexus/typecheck 0.8.4 +- @wrnexus/typecheck 0.8.5 - Documentation: https://wrnexusjs.dev/packages/typecheck - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/ui -- @wrnexus/ui 0.8.4 +- @wrnexus/ui 0.8.5 - Documentation: https://wrnexusjs.dev/packages/ui - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/uploader -- @wrnexus/uploader 0.8.4 +- @wrnexus/uploader 0.8.5 - Documentation: https://wrnexusjs.dev/packages/uploader - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt ## @wrnexus/validation -- @wrnexus/validation 0.8.4 +- @wrnexus/validation 0.8.5 - Documentation: https://wrnexusjs.dev/packages/validation - README and complete exported TypeScript API: https://wrnexusjs.dev/llms-full.txt # UI component catalog -The installed @wrnexus/ui 0.8.4 release contains 108 documented components. The contracts below include every mount name, purpose, prop type, required/default status, slot, and event. Interactive examples live only on the dedicated component showcase. +The installed @wrnexus/ui 0.8.5 release contains 108 documented components. The contracts below include every mount name, purpose, prop type, required/default status, slot, and event. Interactive examples live only on the dedicated component showcase. ### Accordion Showcase: https://component.wrnexusjs.dev/ @@ -867,11 +873,11 @@ Events: select, change ### DataTable Showcase: https://component.wrnexusjs.dev/ Mount: (legacy: data-component="DataTable") -Category: integrations -Purpose: Theme-aware, responsive data table component. -Props: size: string = "default", color: string = "primary", caption: string = "Data Table", columns: unknown[] = [], rows: unknown[] = [], striped: boolean = true, class: string = "" +Category: tables +Purpose: Sortable, filterable, paginated data table with row selection. +Props: color: string = "primary", size: string = "default", columns: unknown[] = [], rows: unknown[] = [], rowKey: string = "id", remote: boolean = false, loadingLabel: string = "Loading", errorLabel: string = "Could not load this data", retryLabel: string = "Try again", caption: string = "", description: string = "", searchable: boolean = true, searchPlaceholder: string = "Search", paginated: boolean = true, pageSize: number = 10, paginationStyle: string = "compact", pageSizes: number[] = [10, 25, 50], selectable: boolean = false, actions: unknown[] = [], striped: boolean = true, bordered: boolean = true, gridlines: string = "rows", density: string = "default", emptyLabel: string = "No records to show", noResultsLabel: string = "No records match your search", clearSearchLabel: string = "Clear search", stickyFirstColumn: boolean = false, layout: string = "rows", class: string = "" Slots: default -Events: sort, select, change, rowClick, pageChange +Events: sort, search, pageChange, select, change, rowClick, action, request ### DatePicker Showcase: https://component.wrnexusjs.dev/ @@ -914,7 +920,7 @@ Showcase: https://component.wrnexusjs.dev/ Mount: (legacy: data-component="Drawer") Category: overlays Purpose: Present responsive modal side or bottom content with focus management, backdrop behavior, slots, and close events. -Props: open: boolean = false, defaultOpen: boolean = false, placement: string = "right", size: string = "md", color: string = "primary", variant: string = "default", title: string = "Drawer", description: string = "", icon: string = "", label: string = "Drawer", closeLabel: string = "Close drawer", showClose: boolean = true, closeOnBackdrop: boolean = true, closeOnEscape: boolean = true, overlay: boolean = true, scrollable: boolean = true, triggerLabel: string = "", triggerIcon: string = "", class: string = "" +Props: open: boolean = false, defaultOpen: boolean = false, placement: string = "right", size: string = "md", color: string = "primary", variant: string = "default", title: string = "Drawer", description: string = "", icon: string = "", label: string = "Drawer", closeLabel: string = "Close drawer", showClose: boolean = true, closeOnBackdrop: boolean = true, closeOnEscape: boolean = true, duration: number = 260, overlay: boolean = true, scrollable: boolean = true, triggerLabel: string = "", triggerIcon: string = "", class: string = "" Slots: trigger, header, default, footer Events: open, close, cancel @@ -1166,7 +1172,7 @@ Showcase: https://component.wrnexusjs.dev/ Mount: (legacy: data-component="Modal") Category: overlays Purpose: Present an accessible modal dialog with focus management, confirmation, cancellation, slots, and responsive sizing. -Props: open: boolean = false, defaultOpen: boolean = false, title: string = "Modal", description: string = "", icon: string = "", label: string = "Modal dialog", size: string = "md", placement: string = "center", color: string = "primary", variant: string = "default", showClose: boolean = true, closeLabel: string = "Close modal", closeOnBackdrop: boolean = true, closeOnEscape: boolean = true, closeOnCancel: boolean = true, closeOnConfirm: boolean = false, showFooter: boolean = true, cancelLabel: string = "Cancel", cancelIcon: string = "", confirmLabel: string = "Confirm", confirmIcon: string = "", confirmDisabled: boolean = false, confirmLoading: boolean = false, destructive: boolean = false, triggerLabel: string = "", triggerIcon: string = "", scrollable: boolean = true, class: string = "" +Props: open: boolean = false, defaultOpen: boolean = false, title: string = "Modal", description: string = "", icon: string = "", label: string = "Modal dialog", size: string = "md", placement: string = "center", color: string = "primary", variant: string = "default", showClose: boolean = true, closeLabel: string = "Close modal", closeOnBackdrop: boolean = true, closeOnEscape: boolean = true, closeOnCancel: boolean = true, closeOnConfirm: boolean = false, showFooter: boolean = true, cancelLabel: string = "Cancel", cancelIcon: string = "", confirmLabel: string = "Confirm", confirmIcon: string = "", confirmDisabled: boolean = false, confirmLoading: boolean = false, destructive: boolean = false, triggerLabel: string = "", triggerIcon: string = "", scrollable: boolean = true, scrollBehavior: string = "inside", class: string = "" Slots: trigger, header, default, footer Events: open, close, cancel, confirm @@ -1413,15 +1419,6 @@ Props: size: string = "default", color: string = "primary", id: string = "", nam Slots: none Events: input, change, focus, blur -### Table -Showcase: https://component.wrnexusjs.dev/ -Mount: (legacy: data-component="Table") -Category: tables -Purpose: Theme-aware, responsive table component. -Props: size: string = "default", color: string = "primary", caption: string = "Table", columns: unknown[] = [], rows: unknown[] = [], striped: boolean = true, class: string = "" -Slots: default -Events: sort, select, rowClick - ### Tabs Showcase: https://component.wrnexusjs.dev/ Mount: (legacy: data-component="Tabs") @@ -1485,6 +1482,15 @@ Props: size: string = "default", color: string = "primary", title: string = "Toa Slots: default Events: add, dismiss, clear, action +### Toaster +Showcase: https://component.wrnexusjs.dev/ +Mount: (legacy: data-component="Toaster") +Category: core +Purpose: Reusable toaster component. +Props: color: string = "info", size: string = "default", position: string = "bottom-right", duration: number = 4500, max: number = 4, pauseOnHover: boolean = true, showIcon: boolean = true, successIcon: string = "", dangerIcon: string = "", warningIcon: string = "", infoIcon: string = "", closable: boolean = true, showProgress: boolean = true, closeLabel: string = "Dismiss notification", class: string = "" +Slots: none +Events: show, dismiss, action + ### ToggleCount Showcase: https://component.wrnexusjs.dev/ Mount: (legacy: data-component="ToggleCount") diff --git a/public/sitemap.xml b/public/sitemap.xml index 8daeb91b..991e3574 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,2 +1,2 @@ -https://wrnexusjs.dev/https://wrnexusjs.dev/accesshttps://wrnexusjs.dev/getting-startedhttps://wrnexusjs.dev/tutorialhttps://wrnexusjs.dev/architecturehttps://wrnexusjs.dev/languagehttps://wrnexusjs.dev/packageshttps://wrnexusjs.dev/guides/project-structurehttps://wrnexusjs.dev/guides/routinghttps://wrnexusjs.dev/guides/pages-and-componentshttps://wrnexusjs.dev/guides/server-datahttps://wrnexusjs.dev/guides/api-routeshttps://wrnexusjs.dev/guides/middlewarehttps://wrnexusjs.dev/guides/forms-and-validationhttps://wrnexusjs.dev/guides/authenticationhttps://wrnexusjs.dev/guides/authorizationhttps://wrnexusjs.dev/guides/securityhttps://wrnexusjs.dev/guides/databasehttps://wrnexusjs.dev/guides/uploadshttps://wrnexusjs.dev/guides/realtimehttps://wrnexusjs.dev/guides/pubsubhttps://wrnexusjs.dev/guides/queueshttps://wrnexusjs.dev/guides/testinghttps://wrnexusjs.dev/guides/workspaces-and-gatewayhttps://wrnexusjs.dev/guides/deploymenthttps://wrnexusjs.dev/guides/configuration-and-profileshttps://wrnexusjs.dev/guides/i18n-and-themeshttps://wrnexusjs.dev/guides/mobilehttps://wrnexusjs.dev/guides/observabilityhttps://wrnexusjs.dev/guides/upgradinghttps://wrnexusjs.dev/guides/troubleshootinghttps://wrnexusjs.dev/exampleshttps://wrnexusjs.dev/showcasehttps://wrnexusjs.dev/benchmarkshttps://wrnexusjs.dev/roadmaphttps://wrnexusjs.dev/changeloghttps://wrnexusjs.dev/releases/0.8.4https://wrnexusjs.dev/securityhttps://wrnexusjs.dev/supporthttps://wrnexusjs.dev/licensehttps://wrnexusjs.dev/searchhttps://wrnexusjs.dev/404https://wrnexusjs.dev/packages/aihttps://wrnexusjs.dev/packages/authhttps://wrnexusjs.dev/packages/authzhttps://wrnexusjs.dev/packages/benchmarkhttps://wrnexusjs.dev/packages/cachehttps://wrnexusjs.dev/packages/captchahttps://wrnexusjs.dev/packages/clihttps://wrnexusjs.dev/packages/compilerhttps://wrnexusjs.dev/packages/contenthttps://wrnexusjs.dev/packages/corehttps://wrnexusjs.dev/packages/csrhttps://wrnexusjs.dev/packages/dbhttps://wrnexusjs.dev/packages/dev-serverhttps://wrnexusjs.dev/packages/dev-toolbarhttps://wrnexusjs.dev/packages/encryptionhttps://wrnexusjs.dev/packages/graphqlhttps://wrnexusjs.dev/packages/helpershttps://wrnexusjs.dev/packages/i18nhttps://wrnexusjs.dev/packages/identityhttps://wrnexusjs.dev/packages/imagehttps://wrnexusjs.dev/packages/jwthttps://wrnexusjs.dev/packages/language-serverhttps://wrnexusjs.dev/packages/mcphttps://wrnexusjs.dev/packages/mobilehttps://wrnexusjs.dev/packages/nativehttps://wrnexusjs.dev/packages/oauthhttps://wrnexusjs.dev/packages/observabilityhttps://wrnexusjs.dev/packages/playgroundhttps://wrnexusjs.dev/packages/pluginhttps://wrnexusjs.dev/packages/pubsubhttps://wrnexusjs.dev/packages/pwahttps://wrnexusjs.dev/packages/queuehttps://wrnexusjs.dev/packages/reactivehttps://wrnexusjs.dev/packages/realtimehttps://wrnexusjs.dev/packages/routerhttps://wrnexusjs.dev/packages/securityhttps://wrnexusjs.dev/packages/ssrhttps://wrnexusjs.dev/packages/storehttps://wrnexusjs.dev/packages/styleshttps://wrnexusjs.dev/packages/syntaxhttps://wrnexusjs.dev/packages/testhttps://wrnexusjs.dev/packages/trackinghttps://wrnexusjs.dev/packages/typecheckhttps://wrnexusjs.dev/packages/uihttps://wrnexusjs.dev/packages/uploaderhttps://wrnexusjs.dev/packages/validation +https://wrnexusjs.dev/https://wrnexusjs.dev/accesshttps://wrnexusjs.dev/getting-startedhttps://wrnexusjs.dev/tutorialhttps://wrnexusjs.dev/architecturehttps://wrnexusjs.dev/languagehttps://wrnexusjs.dev/packageshttps://wrnexusjs.dev/guides/project-structurehttps://wrnexusjs.dev/guides/routinghttps://wrnexusjs.dev/guides/pages-and-componentshttps://wrnexusjs.dev/guides/server-datahttps://wrnexusjs.dev/guides/api-routeshttps://wrnexusjs.dev/guides/middlewarehttps://wrnexusjs.dev/guides/forms-and-validationhttps://wrnexusjs.dev/guides/authenticationhttps://wrnexusjs.dev/guides/authorizationhttps://wrnexusjs.dev/guides/securityhttps://wrnexusjs.dev/guides/databasehttps://wrnexusjs.dev/guides/uploadshttps://wrnexusjs.dev/guides/realtimehttps://wrnexusjs.dev/guides/pubsubhttps://wrnexusjs.dev/guides/queueshttps://wrnexusjs.dev/guides/testinghttps://wrnexusjs.dev/guides/workspaces-and-gatewayhttps://wrnexusjs.dev/guides/deploymenthttps://wrnexusjs.dev/guides/configuration-and-profileshttps://wrnexusjs.dev/guides/i18n-and-themeshttps://wrnexusjs.dev/guides/mobilehttps://wrnexusjs.dev/guides/observabilityhttps://wrnexusjs.dev/guides/upgradinghttps://wrnexusjs.dev/guides/troubleshootinghttps://wrnexusjs.dev/exampleshttps://wrnexusjs.dev/showcasehttps://wrnexusjs.dev/benchmarkshttps://wrnexusjs.dev/roadmaphttps://wrnexusjs.dev/changeloghttps://wrnexusjs.dev/releases/0.8.5https://wrnexusjs.dev/securityhttps://wrnexusjs.dev/supporthttps://wrnexusjs.dev/licensehttps://wrnexusjs.dev/searchhttps://wrnexusjs.dev/404https://wrnexusjs.dev/packages/aihttps://wrnexusjs.dev/packages/authhttps://wrnexusjs.dev/packages/authzhttps://wrnexusjs.dev/packages/benchmarkhttps://wrnexusjs.dev/packages/cachehttps://wrnexusjs.dev/packages/captchahttps://wrnexusjs.dev/packages/clihttps://wrnexusjs.dev/packages/compilerhttps://wrnexusjs.dev/packages/contenthttps://wrnexusjs.dev/packages/corehttps://wrnexusjs.dev/packages/csrhttps://wrnexusjs.dev/packages/dbhttps://wrnexusjs.dev/packages/dev-serverhttps://wrnexusjs.dev/packages/dev-toolbarhttps://wrnexusjs.dev/packages/encryptionhttps://wrnexusjs.dev/packages/graphqlhttps://wrnexusjs.dev/packages/helpershttps://wrnexusjs.dev/packages/i18nhttps://wrnexusjs.dev/packages/identityhttps://wrnexusjs.dev/packages/imagehttps://wrnexusjs.dev/packages/jwthttps://wrnexusjs.dev/packages/language-serverhttps://wrnexusjs.dev/packages/mcphttps://wrnexusjs.dev/packages/mobilehttps://wrnexusjs.dev/packages/nativehttps://wrnexusjs.dev/packages/oauthhttps://wrnexusjs.dev/packages/observabilityhttps://wrnexusjs.dev/packages/playgroundhttps://wrnexusjs.dev/packages/pluginhttps://wrnexusjs.dev/packages/pubsubhttps://wrnexusjs.dev/packages/pwahttps://wrnexusjs.dev/packages/queuehttps://wrnexusjs.dev/packages/reactivehttps://wrnexusjs.dev/packages/realtimehttps://wrnexusjs.dev/packages/routerhttps://wrnexusjs.dev/packages/rpchttps://wrnexusjs.dev/packages/securityhttps://wrnexusjs.dev/packages/ssrhttps://wrnexusjs.dev/packages/storehttps://wrnexusjs.dev/packages/styleshttps://wrnexusjs.dev/packages/syntaxhttps://wrnexusjs.dev/packages/testhttps://wrnexusjs.dev/packages/trackinghttps://wrnexusjs.dev/packages/typecheckhttps://wrnexusjs.dev/packages/uihttps://wrnexusjs.dev/packages/uploaderhttps://wrnexusjs.dev/packages/validation