create-prisma-php-app 5.1.0-alpha.3 → 5.1.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +23 -2
  2. package/dist/.github/copilot-instructions.md +80 -33
  3. package/dist/AGENTS.md +59 -25
  4. package/dist/bootstrap.php +207 -187
  5. package/dist/index.js +2 -2
  6. package/dist/phpunit.xml +25 -0
  7. package/dist/postcss.config.js +4 -2
  8. package/dist/public/.htaccess +1 -1
  9. package/dist/public/js/pp-reactive-v2.min.js +1 -0
  10. package/dist/settings/bs-config.ts +44 -1
  11. package/dist/settings/run-postcss.ts +205 -0
  12. package/dist/settings/run-tests.ts +35 -0
  13. package/dist/src/Lib/Auth/Auth.php +12 -25
  14. package/dist/src/Lib/MCP/mcp-server.php +2 -3
  15. package/dist/src/Lib/Websocket/ConnectionManager.php +500 -47
  16. package/dist/src/Lib/Websocket/Socket.php +170 -0
  17. package/dist/src/Lib/Websocket/SocketPool.php +50 -0
  18. package/dist/src/Lib/Websocket/SocketRegistry.php +88 -0
  19. package/dist/src/Lib/Websocket/sockets.php +50 -0
  20. package/dist/src/Lib/Websocket/websocket-server.php +10 -3
  21. package/dist/src/app/globals.css +3 -1
  22. package/dist/src/app/layout.php +1 -1
  23. package/dist/tests/AuthTest.php +59 -0
  24. package/dist/tests/ConnectionManagerTest.php +277 -0
  25. package/dist/tests/CsrfTest.php +119 -0
  26. package/dist/tests/DeferComponentRootsTest.php +147 -0
  27. package/dist/tests/FeaturesTest.php +41 -0
  28. package/dist/tests/README.md +119 -0
  29. package/dist/tests/RpcWireContractTest.php +101 -0
  30. package/dist/tests/SocketPoolTest.php +69 -0
  31. package/dist/tests/SocketRegistryTest.php +77 -0
  32. package/dist/tests/SocketTest.php +124 -0
  33. package/dist/tests/SocketsRegistrationTest.php +40 -0
  34. package/dist/tests/Support/FakeConnection.php +62 -0
  35. package/dist/tests/Support/Features.php +38 -0
  36. package/dist/tests/Support/RequiresFeature.php +26 -0
  37. package/dist/tests/bootstrap.php +44 -0
  38. package/dist/ts/main.ts +5 -8
  39. package/dist/ts/tailwind-merge.ts +13 -0
  40. package/package.json +4 -4
  41. package/dist/public/js/pp-reactive-v2.js +0 -1
package/README.md CHANGED
@@ -36,10 +36,14 @@ If you are using XAMPP on Windows, enabling `extension=zip` in `php.ini` is reco
36
36
  Prisma PHP brings together the core pieces needed to build full-stack PHP apps:
37
37
 
38
38
  - **Native PHP + modern reactivity** with PulsePoint
39
+ - **Direct RPC from the frontend** with `pp.rpc(...)` calling `#[Exposed]` PHP functions — JSON in, JSON out, SSE streaming when the function yields, and framework failures reported as real HTTP statuses
40
+ - **Named sockets for realtime** with `pp.socket(...)` — long-lived bidirectional messaging (chat, presence, live feeds) served by a Ratchet-based socket server with per-socket auth, origin checks, and rate limits
39
41
  - **PHPX component system** for reusable UI composition
40
42
  - **Prisma PHP ORM** for schema-first, type-safe database access
41
43
  - **Built-in authentication patterns** for sessions, route protection, RBAC, credentials auth, and provider login
44
+ - **Hardened request pipeline** with double-submit CSRF (`pp_csrf` cookie family), origin validation, content-type checks, and per-function rate limiting
42
45
  - **File-based routing** with clear route file conventions
46
+ - **App-level test suite** with PHPUnit in a root `tests/` directory, run with `npm run test`, feature-aware via `prisma-php.json`
43
47
  - **CLI scaffolding** for new apps, starter kits, and optional features
44
48
  - **Flexible deployment options** for local development and production workflows
45
49
 
@@ -117,7 +121,10 @@ Use these docs as the main entry points for common work:
117
121
  - `project-structure.md` for project structure, route placement, and file conventions
118
122
  - `layouts-and-pages.md` for pages, layouts, nested routes, and dynamic routes
119
123
  - `components.md` for PHPX components, props, children, fragments, icons, buttons, and composition
120
- - `fetching-data.md` for `pp.fetchFunction(...)`, `#[Exposed]`, and interactive backend flows
124
+ - `fetching-data.md` for `pp.rpc(...)`, `#[Exposed]`, streaming, and the RPC error contract
125
+ - `websocket.md` for named sockets, `pp.socket(...)`, `SocketRegistry`, and the realtime wire contract
126
+ - `bootstrap-runtime.md` for the runtime init order, PulsePoint wire headers, and the `pp_csrf` CSRF contract
127
+ - `testing.md` for the root `tests/` directory, `npm run test`, and feature-gated tests
121
128
  - `prisma-php-orm.md` for Prisma ORM, `schema.prisma`, migrations, and generated PHP classes
122
129
  - `authentication.md` for auth strategy, sessions, RBAC, credentials auth, and provider flows
123
130
  - `file-manager.md` for uploads, `multipart/form-data`, `$_FILES`, and `PP\FileManager\UploadFile`
@@ -152,13 +159,15 @@ For task-specific route decision rules and framework generation rules, read `AGE
152
159
 
153
160
  ## PulsePoint and Frontend Reactivity
154
161
 
155
- Prisma PHP uses PulsePoint for browser-side reactivity.
162
+ Prisma PHP uses PulsePoint for browser-side reactivity and as the wire between the page and PHP.
156
163
 
157
164
  When working with runtime features such as:
158
165
 
159
166
  - `pp.state`
160
167
  - `pp.effect`
161
168
  - `pp.ref`
169
+ - `pp.rpc` for frontend-to-PHP calls (with streaming, uploads, and redirects)
170
+ - `pp.socket` for named-socket realtime messaging
162
171
  - `pp-for`
163
172
  - `pp-spread`
164
173
  - `pp-ref`
@@ -179,11 +188,23 @@ prisma-php-project/
179
188
  ├── public/ # public entry point and assets
180
189
  ├── settings/ # project configuration
181
190
  ├── src/ # application source code
191
+ ├── tests/ # app-level PHPUnit tests (npm run test)
182
192
  ├── package.json # frontend/dev scripts
183
193
  ├── composer.json # PHP dependencies
194
+ ├── phpunit.xml # test suite configuration
184
195
  └── prisma-php.json # Prisma PHP project capability manifest
185
196
  ```
186
197
 
198
+ ## Testing
199
+
200
+ App tests live in the root `tests/` directory and run with:
201
+
202
+ ```bash
203
+ npm run test
204
+ ```
205
+
206
+ The suite runs PHPUnit on the PHP binary configured in `prisma-php.json`, uses a deterministic test environment (the real `.env` is never loaded), and is feature-aware: tests for optional features such as WebSocket skip cleanly when the feature is disabled in `prisma-php.json`. Read `testing.md` in the installed docs and the project's `tests/README.md` for the full contract.
207
+
187
208
  ## Updating Existing Projects
188
209
 
189
210
  When enabling features or syncing framework-managed project files:
@@ -7,13 +7,14 @@
7
7
  - Treat `node_modules/prisma-php/dist/docs` as framework reference docs that teach AI how Prisma PHP works. The presence of a page in that docs folder does not mean the current workspace has that feature enabled.
8
8
  - Read the matching doc in `node_modules/prisma-php/dist/docs` before generating or editing framework-specific Prisma PHP code.
9
9
  - Expect `AGENTS.md` in the project root and keep it aligned with the installed Prisma PHP docs contract.
10
- - In the Prisma PHP package source repo, keep `AGENTS.md`, `.github/copilot-instructions.md`, any `.github/instructions/**/*.instructions.md`, and `dist/docs` aligned so the published docs remain correct after install.
10
+ - In the Prisma PHP package source repo, keep the source-repo `AGENTS.md`, `.github/copilot-instructions.md`, any `.github/instructions/**/*.instructions.md`, and source-repo `dist/docs` aligned so the published docs remain correct after install. In consumer apps, the installed docs path is `node_modules/prisma-php/dist/docs`.
11
11
  - Do not assume installed consumer apps also ship a root `.github/copilot-instructions.md` unless the generator explicitly creates one.
12
12
  - If `.github/instructions/**/*.instructions.md` exists, treat those files as workspace-local task instructions for third-party libraries, component systems, icon packs, and other implementation-specific rules.
13
13
  - Before generating or editing code, inspect `.github/instructions/` and read any `*.instructions.md` files that match the current task, named library, target files, or implementation surface.
14
- - Keep every `dist/docs/*.md` page AI-discoverable on its own: the frontmatter description and opening section should clearly say when agents should read that file and which adjacent docs to consult next.
14
+ - In the Prisma PHP package source repo, keep every `dist/docs/*.md` page AI-discoverable on its own. In consumer apps, those installed docs live at `node_modules/prisma-php/dist/docs/*.md`. The frontmatter description and opening section should clearly say when agents should read that file and which adjacent docs to consult next.
15
15
  - When a task maps to an optional feature such as `backendOnly`, `swaggerDocs`, `typescript`, `websocket`, or `mcp`, inspect `./prisma-php.json` first, then read the matching docs page to learn the implementation contract.
16
- - When docs and project files still leave a runtime gap, inspect the narrow core file that owns the behavior: `TemplateCompiler.php` for HTML fragment compilation and route root scoping, `ImportComponent.php` for imported partials, `MainLayout.php` for metadata and head/footer scripts, `PrismaPHPSettings.php` plus generated settings JSON for component and route maps, `Request.php` for request handling, `Validator.php`/`Rule.php` for validation, and feature-specific files such as `UploadFile.php`, `Mailer.php`, or `Streaming/SSE.php`.
16
+ - When docs and project files still leave a runtime gap, inspect the narrow core file that owns the behavior: `TemplateCompiler.php` for HTML fragment compilation and route root scoping, `PHPX.php` plus `TwMerge.php` for PHPX class composition and frontend `twMerge(...)` emission, `ImportComponent.php` for imported partials, `MainLayout.php` for metadata and head/footer scripts, `PrismaPHPSettings.php` plus generated settings JSON for component and route maps, `Request.php` for request handling, `Validator.php`/`Rule.php` for validation, and feature-specific files such as `UploadFile.php`, `Mailer.php`, or `Streaming/SSE.php`.
17
+ - When validation or rule-builder syntax is involved, read `node_modules/prisma-php/dist/docs/validator.md` first. If method shape is still unclear after that, inspect `vendor/tsnc/prisma-php/src/Rule.php` to confirm which `Rule` methods are static entry points and which methods must be chained on a builder instance.
17
18
 
18
19
  ## Workspace Task Instructions
19
20
 
@@ -28,9 +29,11 @@
28
29
  - Keep `src/app` focused on route files, layouts, handlers, and route-scoped partials.
29
30
  - Prefer `src/Components` for reusable application UI components shared across pages or layouts.
30
31
  - Keep reusable non-UI code such as services, auth, middleware, Prisma classes, and helpers in `src/Lib`.
32
+ - Treat route-private folders such as `src/app/<route>/_components` as an implementation detail for files that stay owned by that route only.
31
33
  - Treat `./public/uploads` as the default local public upload directory for file uploads.
32
34
  - Treat generated component libraries such as `src/Lib/PHPXUI` and `src/Lib/PPIcons` as library-specific surfaces governed by their manifests and `.github/instructions/*.instructions.md` files.
33
35
  - If a partial starts as route-local but becomes shared across the app, move it from `src/app` to `src/Components`.
36
+ - Do not default to creating `src/app/<route>/_components` for app-owned section components such as `HeroSection`, `FormSection`, or `SidebarSection`; prefer `src/Components` unless the user explicitly wants route-local colocation and the files are truly private to that route.
34
37
  - Suggest this structure by default when helping users organize growing Prisma PHP apps.
35
38
 
36
39
  ## Component Tag Contract
@@ -43,6 +46,14 @@
43
46
  - Use mustache values for reactive props, such as `selected-date="{selectedDate}"` and `on-date-select="{setSelectedDate}"`.
44
47
  - Write component examples as HTML-first Prisma PHP markup using the current `x-` tag contract.
45
48
 
49
+ ## Tailwind Merge Contract
50
+
51
+ - In Tailwind-enabled Prisma PHP apps, Tailwind utility conflict resolution belongs to the frontend `twMerge(...)` runtime helper.
52
+ - `getMergeClasses(...)` and `PP\PHPX\TwMerge::merge(...)` emit frontend `twMerge(...)` expressions for the browser runtime to resolve.
53
+ - `twMerge(...)` is an app-level browser helper, not a PulsePoint built-in.
54
+ - In TypeScript-enabled apps, Prisma PHP registers that helper from `ts/main.ts`; in non-TypeScript Tailwind apps it is registered from `public/js/main.js` (importing `public/js/tailwind-merge.mjs`). Use `typescript.md` for route usage and `components.md` for PHPX usage.
55
+ - Keep Tailwind merge decisions on the frontend runtime instead of trying to finalize conflicting utility classes in PHP.
56
+
46
57
  ## Framework-Managed Package Scripts
47
58
 
48
59
  - Prisma PHP can generate `package.json` scripts for BrowserSync, Tailwind, TypeScript, WebSocket, MCP, Swagger docs, and related helpers.
@@ -50,7 +61,7 @@
50
61
  - Do not default to telling users to run `npm run tailwind`, `npm run tailwind:build`, `npm run ts:watch`, or `npm run ts:build` after routine file changes, because those are usually orchestrated through the generated top-level scripts.
51
62
  - Use `npm run websocket` or `npm run mcp` only when isolating local runtime startup, debugging, or when the project's scripts show those services are not already covered by the normal development flow.
52
63
  - Use `npm run create-swagger-docs` only when Swagger or OpenAPI output must be intentionally generated or refreshed.
53
- - When package-script behavior matters, read `dist/docs/commands.md` first and inspect the actual `package.json` in the target project before assuming which scripts exist.
64
+ - When package-script behavior matters, read `node_modules/prisma-php/dist/docs/commands.md` first and inspect the actual `package.json` in the target project before assuming which scripts exist.
54
65
 
55
66
  ## BrowserSync URL Source Of Truth
56
67
 
@@ -79,6 +90,7 @@
79
90
  ## Authentication Route Strategy
80
91
 
81
92
  - Prisma PHP defaults to public routes.
93
+ - Auth classes are app-owned under `src/Lib/Auth` in the `Lib\Auth` namespace: `use Lib\Auth\Auth;`, `use Lib\Auth\AuthConfig;`, `use Lib\Auth\AuthRole;` — never `PP\Auth\...`.
82
94
  - Choose the route privacy strategy at the start of the app, before creating most routes.
83
95
  - If the app will have many public pages, keep the public-default strategy.
84
96
  - If the app will have only a few public entry points and most routes should require login, use the private-default strategy.
@@ -91,20 +103,32 @@
91
103
  ## PulsePoint-First Frontend Rules
92
104
 
93
105
  - In full-stack Prisma PHP apps, treat PulsePoint as the primary JavaScript authoring model for frontend behavior.
94
- - For page-local interactivity, prefer `index.php` or nested `layout.php` with a plain inline `<script>` that contains PulsePoint state and functions directly, and use `pp.fetchFunction(...)` for backend calls.
106
+ - For page-local interactivity, prefer `index.php` or nested `layout.php` with a plain inline `<script>` that contains PulsePoint state and functions directly, and use `pp.rpc(...)` for backend calls.
95
107
  - Do not wrap inline PulsePoint code in `DOMContentLoaded`, IIFEs, manual `pp.mount()` calls, or custom scoping/bootstrap helpers. Prisma PHP scopes the component boundary and runs the script for you.
96
108
  - Reserve plain browser JavaScript or TypeScript modules for reusable helpers in `ts/`, third-party libraries, low-level browser APIs, or behavior that does not belong inside a PulsePoint component boundary.
97
- - Use `pp-style` for template-driven inline CSS, `pp-spread="{...attrs}"` for dynamic attribute objects, `pp-for` only on `<template>`, and plain `key` for keyed diffing.
109
+ - Do not treat app-registered helpers such as `twMerge(...)` as PulsePoint built-ins; only use them after the relevant Prisma PHP feature flag and entry-file docs confirm they exist.
110
+ - Use `pp-style` whenever inline CSS contains `{...}` interpolation or any other template-driven/reactive value, reserve plain `style` for fully static inline CSS, use `pp-spread="{...attrs}"` for dynamic attribute objects, keep `pp-for` only on `<template>`, and use plain `key` for keyed diffing.
111
+ - Do not generate reactive inline CSS inside a plain `style` attribute such as `style="width: {progress}%";` use `pp-style="width: {progress}%";` instead so editor CSS validation does not flag the source markup as invalid.
98
112
  - Use `pp.ref(...)`, `pp-ref`, `pp.portal(...)`, `pp.createContext(...)`, `Context.Provider`, and `pp.context(...)` according to `pulsepoint.md`.
99
113
  - Use `value`, `defaultvalue`, and `defaultchecked` form bindings according to `pulsepoint.md`; do not author internal `data-pp-*` runtime attributes.
100
114
 
115
+ ## Runtime Wire Contract
116
+
117
+ - `pp.rpc(functionName, data?, optionsOrAbort?)` is the frontend-to-PHP call API.
118
+ - Every function called through `pp.rpc(...)` must be marked `#[Exposed]` on the PHP side.
119
+ - Framework-level RPC failures (unknown function, auth, roles, CSRF, origin, content type, rate limit, server error) arrive as HTTP error statuses with an `{"error": "..."}` JSON body and reject the `pp.rpc(...)` promise; wrap calls in `try/catch` when the UI reacts to failures. Return routine validation feedback as structured data instead of throwing. Throwing `InvalidArgumentException` in an exposed function is the sanctioned validation crossover: its message reaches the caller as a 400.
120
+ - Streamed responses: an exposed function that yields streams SSE `data:` lines; consume them with `onStream`, `onStreamError`, and `onStreamComplete`.
121
+ - CSRF: the runtime reads the `pp_csrf` cookie family (`pp_csrf_<port>` in development, `pp_csrf` otherwise), managed server-side by `PP\Security\Csrf` and signed with `FUNCTION_CALL_SECRET`.
122
+ - Realtime: use `pp.socket(name, args, handlers)` (named sockets) for long-lived bidirectional flows. Server handlers are registered with `SocketRegistry::register(...)` in `src/Lib/Websocket/sockets.php`; the wire is one endpoint (`/__pulsepoint/ws?name=...`), arguments as the first JSON frame, JSON frames both ways, and `{"error": "..."}` reserved for failures. Do not generate raw `new WebSocket(...)` wiring for app realtime work.
123
+ - Read `node_modules/prisma-php/dist/docs/fetching-data.md`, `bootstrap-runtime.md`, and `websocket.md` for the full contracts.
124
+
101
125
  ## Route File Conventions
102
126
 
103
127
  - For PulsePoint-aware `index.php` and nested `layout.php`, keep file order as PHP first, then one parent HTML element as the route boundary, then the visible route content inside that boundary, and keep the PulsePoint `<script>` as the last child of that boundary root.
104
128
  - `index.php` and nested `layout.php` must render a single parent HTML element. Treat that root like a component boundary rather than loose sibling markup.
105
129
  - If the visible page or layout content should stay inside a semantic element such as `<main>`, `<section>`, or `<article>`, wrap it in a neutral parent such as `<div>` so the route boundary can still own the `<script>`.
106
130
  - For pages and nested layouts, author a plain single root element and let Prisma PHP inject the PulsePoint `pp-component` scope automatically.
107
- - Author plain `<script>` tags inside that boundary root when PulsePoint is needed, usually as a sibling of the visible content container instead of nesting the script inside the semantic content element by default. Put the PulsePoint code at the top level of that script. Do not manually add `type="text/pp"`, `DOMContentLoaded` wrappers, IIFEs, or manual bootstrap code; Prisma PHP normalizes the script contract for the runtime.
131
+ - Author plain `<script>` tags inside that boundary root when PulsePoint is needed, usually as a sibling of the visible content container instead of nesting the script inside the semantic content element by default. Put the PulsePoint code at the top level of that script. Never put a `type` attribute on a component script — the runtime only recognizes untyped scripts. Do not add `DOMContentLoaded` wrappers, IIFEs, or manual bootstrap code.
108
132
  - Do not leave the route `<script>` outside the route boundary.
109
133
  - Only the root `layout.php` should define `<html>`, `<head>`, and `<body>`. When PulsePoint is present, keep `MainLayout::$children;` and any `<script>` inside one clear wrapper.
110
134
 
@@ -113,32 +137,55 @@
113
137
  - Distinguish PHPX class components from `ImportComponent` partials.
114
138
  - `ImportComponent` partials must output exactly one root element because Prisma PHP uses that root as the imported component boundary and serializes props there.
115
139
  - Do not manually add `pp-component` inside `ImportComponent` partial source; Prisma PHP injects it there.
116
- - When imported partials need PulsePoint logic, keep the `<script>` inside that same root element and author it as a plain `<script>` tag without `type="text/pp"`, DOM-ready wrappers, or manual bootstrap code.
140
+ - When imported partials need PulsePoint logic, keep the `<script>` inside that same root element and author it as a plain `<script>` tag with no `type` attribute (the runtime ignores typed scripts), without DOM-ready wrappers or manual bootstrap code.
141
+
142
+ ## Validation Rules
143
+
144
+ - Use `PP\Validator` as the backend validation and normalization layer.
145
+ - Prefer the `Rule` builder for rule-based validation.
146
+ - Start `Rule` builders with `Rule::required()`, `Rule::optional()`, or `Rule::make()`.
147
+ - Chain rule methods such as `->min(...)`, `->max(...)`, `->email()`, and `->regex(...)` on that builder instance.
148
+ - Do not generate static calls such as `Rule::max(80)` or `Rule::email()`.
149
+ - For optional constrained fields, use `Rule::optional()->max(80)` or `Rule::make()->max(80)`.
150
+ - Validate in PHP even when the frontend already performs local checks.
151
+ - Return structured validation results for expected failures instead of treating routine invalid input as an uncaught exception.
152
+ - When internals matter, inspect `vendor/tsnc/prisma-php/src/Validator.php` and `vendor/tsnc/prisma-php/src/Rule.php`.
153
+
154
+ ## Testing Rules
155
+
156
+ - App tests live in the root `tests/` directory and run with `npm run test` (PHPUnit via `settings/run-tests.ts`, using the PHP binary from `prisma-php.json`). Narrow runs with `npm run test -- --filter <NameOrMethod>`.
157
+ - When adding or changing app behavior with logic worth protecting (exposed-function validation, socket handlers, auth rules, `src/Lib` helpers), add or update the matching `tests/*Test.php` in the same change and run `npm run test` before declaring the work done.
158
+ - Tests cover app-level code and the wire contracts the app depends on; do not test Prisma PHP framework internals from the app suite.
159
+ - Tests of optional features (`websocket`, `mcp`, `swaggerDocs`, `prisma`, ...) must guard on the `prisma-php.json` flag via the `Tests\Support\RequiresFeature` trait (`$this->requireFeature('websocket')` as the first line of `setUp()`), so a disabled feature skips cleanly instead of fataling on missing scaffold classes. Core surfaces (CSRF, wire headers, auth) are never gated.
160
+ - `tests/bootstrap.php` sets a deterministic env (no real `.env`); shared fakes live in `tests/Support` (`Tests\Support\...`). Socket wire tests use `Tests\Support\FakeConnection` and assert frames plus close codes.
161
+ - Read `node_modules/prisma-php/dist/docs/testing.md` and the project's `tests/README.md` before writing tests.
117
162
 
118
163
  ## Relevant Docs
119
164
 
120
- - Project structure and feature placement: `dist/docs/project-structure.md`
121
- - CLI project creation and update commands: `dist/docs/commands.md`
122
- - First-time project installation and local setup: `dist/docs/installation.md`
123
- - Existing-project upgrades and feature refreshes: `dist/docs/upgrading.md`
124
- - TypeScript frontend tooling, the `typescript` flag, and `ts/main.ts` registration: `dist/docs/typescript.md`
125
- - Backend-only API usage and `backendOnly`: `dist/docs/backend-only.md`
126
- - Route and layout structure: `dist/docs/layouts-and-pages.md`
127
- - AI integration, provider-backed chat, streaming, and MCP boundary: `dist/docs/get-started-ia.md`
128
- - Data loading, `#[Exposed]`, and SSE streaming: `dist/docs/fetching-data.md`
129
- - Bootstrap flow, runtime init order, request initialization, and function-call protection: `dist/docs/bootstrap-runtime.md`
130
- - PulsePoint runtime rules: `dist/docs/pulsepoint.md`
131
- - Component and `ImportComponent` rules: `dist/docs/components.md`
132
- - Cache behavior and `CacheHandler`: `dist/docs/caching.md`
133
- - Validation rules: `dist/docs/validator.md`
134
- - Prisma ORM schema, migrations, and generated PHP classes: `dist/docs/prisma-php-orm.md`
135
- - Environment variables and `PP\Env` usage: `dist/docs/env.md`
136
- - File uploads and file manager behavior: `dist/docs/file-manager.md`
137
- - Email and SMTP workflows: `dist/docs/email.md`
138
- - WebSocket and realtime behavior: `dist/docs/websocket.md`
139
- - MCP server and tool rules: `dist/docs/mcp.md`
140
- - Authentication: `dist/docs/authentication.md`
141
- - Error handling, expected failures, and route error files: `dist/docs/error-handling.md`
142
- - Metadata and icons: `dist/docs/metadata-and-og-images.md`
143
- - API-style handlers and webhooks: `dist/docs/route-handlers.md`
144
- - Swagger/OpenAPI generation and `swaggerDocs`: `dist/docs/swagger-docs.md`
165
+ - Project structure and feature placement: `node_modules/prisma-php/dist/docs/project-structure.md`
166
+ - CLI project creation and update commands: `node_modules/prisma-php/dist/docs/commands.md`
167
+ - First-time project installation and local setup: `node_modules/prisma-php/dist/docs/installation.md`
168
+ - Existing-project upgrades and feature refreshes: `node_modules/prisma-php/dist/docs/upgrading.md`
169
+ - TypeScript frontend tooling, the `typescript` flag, and `ts/main.ts` registration: `node_modules/prisma-php/dist/docs/typescript.md`
170
+ - Backend-only API usage and `backendOnly`: `node_modules/prisma-php/dist/docs/backend-only.md`
171
+ - Route and layout structure: `node_modules/prisma-php/dist/docs/layouts-and-pages.md`
172
+ - AI integration, provider-backed chat, streaming, and MCP boundary: `node_modules/prisma-php/dist/docs/get-started-ia.md`
173
+ - Data loading, `#[Exposed]`, and SSE streaming: `node_modules/prisma-php/dist/docs/fetching-data.md`
174
+ - Bootstrap flow, runtime init order, request initialization, and function-call protection: `node_modules/prisma-php/dist/docs/bootstrap-runtime.md`
175
+ - PulsePoint runtime rules: `node_modules/prisma-php/dist/docs/pulsepoint.md`
176
+ - Component and `ImportComponent` rules: `node_modules/prisma-php/dist/docs/components.md`
177
+ - Frontend Tailwind class composition and `twMerge(...)`: `node_modules/prisma-php/dist/docs/components.md`, `node_modules/prisma-php/dist/docs/typescript.md`, and `node_modules/prisma-php/dist/docs/layouts-and-pages.md`
178
+ - Cache behavior and `CacheHandler`: `node_modules/prisma-php/dist/docs/caching.md`
179
+ - Validation rules: `node_modules/prisma-php/dist/docs/validator.md`
180
+ - Prisma ORM schema, migrations, and generated PHP classes: `node_modules/prisma-php/dist/docs/prisma-php-orm.md`
181
+ - Environment variables and `PP\Env` usage: `node_modules/prisma-php/dist/docs/env.md`
182
+ - File uploads and file manager behavior: `node_modules/prisma-php/dist/docs/file-manager.md`
183
+ - Email and SMTP workflows: `node_modules/prisma-php/dist/docs/email.md`
184
+ - WebSocket and realtime behavior: `node_modules/prisma-php/dist/docs/websocket.md`
185
+ - MCP server and tool rules: `node_modules/prisma-php/dist/docs/mcp.md`
186
+ - Authentication: `node_modules/prisma-php/dist/docs/authentication.md`
187
+ - Error handling, expected failures, and route error files: `node_modules/prisma-php/dist/docs/error-handling.md`
188
+ - Metadata and icons: `node_modules/prisma-php/dist/docs/metadata-and-og-images.md`
189
+ - API-style handlers and webhooks: `node_modules/prisma-php/dist/docs/route-handlers.md`
190
+ - Swagger/OpenAPI generation and `swaggerDocs`: `node_modules/prisma-php/dist/docs/swagger-docs.md`
191
+ - App test suite, `tests/` layout, and `npm run test`: `node_modules/prisma-php/dist/docs/testing.md`
package/dist/AGENTS.md CHANGED
@@ -35,7 +35,8 @@ Important rules:
35
35
  - expect `./AGENTS.md` at the project root
36
36
  - when the installed docs and a habit from another framework conflict, follow Prisma PHP
37
37
  - when a workspace instruction file and the general Prisma PHP docs both apply, follow both; keep `./prisma-php.json` as the source of truth for feature enablement and prefer the most specific matching instruction for library- or file-scoped implementation details
38
- - when updating Prisma PHP package/docs sources, keep `AGENTS.md` and `dist/docs` aligned for consumer apps; if the Prisma PHP package source repo also maintains `.github/copilot-instructions.md` or `.github/instructions/**/*.instructions.md`, keep those source-repo files aligned there too
38
+ - in consumer apps, use `./node_modules/prisma-php/dist/docs` as the installed docs location; do not assume a root-level `./dist/docs` directory exists
39
+ - when updating Prisma PHP package/docs sources in the Prisma PHP package source repo, keep the source-repo `AGENTS.md` and source-repo `dist/docs` aligned; if that repo also maintains `.github/copilot-instructions.md` or `.github/instructions/**/*.instructions.md`, keep those source-repo files aligned there too
39
40
 
40
41
  ## Runtime lookup for AI
41
42
 
@@ -44,10 +45,12 @@ Use this map only after `prisma-php.json`, matching workspace instructions, inst
44
45
  | Need to verify | Runtime/source file |
45
46
  | --- | --- |
46
47
  | route root scoping, HTML fragment parsing, component tag compilation, prop casing | `vendor/tsnc/prisma-php/src/PHPX/TemplateCompiler.php` |
48
+ | PHPX class composition, `getMergeClasses(...)`, and frontend `twMerge(...)` expression generation | `vendor/tsnc/prisma-php/src/PHPX/PHPX.php`, `vendor/tsnc/prisma-php/src/PHPX/TwMerge.php` |
47
49
  | imported PHP partial execution, one-root enforcement, prop serialization, imported `#[Exposed]` functions | `vendor/tsnc/prisma-php/src/ImportComponent.php` |
48
50
  | metadata, custom head tags, dynamic head/footer scripts | `vendor/tsnc/prisma-php/src/MainLayout.php` |
49
51
  | route and component maps | `vendor/tsnc/prisma-php/src/PrismaPHPSettings.php`, `settings/files-list.json`, `settings/component-map.json` |
50
- | request data, dynamic params, redirects, function-call requests | `vendor/tsnc/prisma-php/src/Request.php` |
52
+ | request data, dynamic params, redirects, RPC/navigation wire detection (`$isRpc`, `$isNavigation`, `$isWire`) | `vendor/tsnc/prisma-php/src/Request.php` |
53
+ | CSRF cookie family (`pp_csrf`, `pp_csrf_<port>`), token issuing and validation | `vendor/tsnc/prisma-php/src/Security/Csrf.php` |
51
54
  | exposed functions | `vendor/tsnc/prisma-php/src/Attributes/Exposed.php`, `vendor/tsnc/prisma-php/src/Attributes/ExposedRegistry.php` |
52
55
  | validation | `vendor/tsnc/prisma-php/src/Validator.php`, `vendor/tsnc/prisma-php/src/Rule.php` |
53
56
  | env values | `vendor/tsnc/prisma-php/src/Env.php` |
@@ -116,10 +119,13 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
116
119
  - **Creating, editing, composing, or reviewing PHPX components, props, children, fragments, icons, buttons, accordions, or component file placement**
117
120
  Read `components.md`
118
121
 
122
+ - **Tailwind utility class composition, `getMergeClasses(...)`, `PP\PHPX\TwMerge`, or frontend `twMerge(...)` usage**
123
+ Confirm `tailwindcss` in `prisma-php.json`, then read `components.md` for PHPX emission, `typescript.md` for app-level helper registration, and `layouts-and-pages.md` for route examples
124
+
119
125
  - **TypeScript frontend tooling, the `typescript` feature flag, the root `ts/` directory, `ts/main.ts`, npm packages, or registered browser helpers used from template expressions and PulsePoint scripts**
120
126
  Read `typescript.md`, then use `pulsepoint.md`, `layouts-and-pages.md`, or `components.md` for the affected component boundary
121
127
 
122
- - **Loading data, calling backend logic from the frontend, `pp.fetchFunction(...)`, `#[Exposed]`, route-local mutations, streaming responses, or interactive backend validation**
128
+ - **Loading data, calling backend logic from the frontend, `pp.rpc(...)`, `#[Exposed]`, route-local mutations, streaming responses, or interactive backend validation**
123
129
  Read `fetching-data.md`
124
130
 
125
131
  - **AI integration, provider SDKs, chat UIs, streamed assistant output, or deciding between page-local assistant UI, websocket, and MCP tools**
@@ -134,7 +140,7 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
134
140
  - **Environment variables, `.env`, `PP\Env`, `Env::get`, `Env::string`, `Env::bool`, `Env::int`, feature flags, host and port config, or runtime bootstrap settings**
135
141
  Read `env.md`, then verify the official env docs at `env` and `env-file`
136
142
 
137
- - **Bootstrap flow, request initialization, `FUNCTION_CALL_SECRET`, `prisma_php_csrf`, route resolution, or runtime init order**
143
+ - **Bootstrap flow, request initialization, `FUNCTION_CALL_SECRET`, `pp_csrf`, route resolution, or runtime init order**
138
144
  Read `bootstrap-runtime.md`, then use `env.md`, `fetching-data.md`, or `error-handling.md` as needed
139
145
 
140
146
  - **File uploads, `multipart/form-data`, `$_FILES`, `PP\FileManager\UploadFile`, rename flows, replace flows, delete flows, allowed file types, upload size rules, or file manager UI behavior**
@@ -143,7 +149,7 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
143
149
  - **SMTP setup, `.env` mail variables, `PP\PHPMailer\Mailer`, HTML bodies, plain-text bodies, recipients, reply-to, CC, BCC, or attachments**
144
150
  Read `email.md`, then verify the official email docs at `email-get-started`
145
151
 
146
- - **Ratchet websocket setup, `IoServer`, `HttpServer`, `WsServer`, `ConnectionManager`, browser `WebSocket`, or realtime route behavior**
152
+ - **Named sockets, `pp.socket(...)`, `SocketRegistry`, `Socket`, `SocketPool`, the Ratchet socket server, or realtime route behavior**
147
153
  Read `websocket.md`, then verify the official websocket docs in this order: `websocket-get-started`, `websocket-chat-app`
148
154
 
149
155
  - **MCP support, `#[McpTool]`, `#[Schema]`, `PhpMcp\Server\Server`, `StreamableHttpServerTransport`, AI tool endpoints, or `src/Lib/MCP/mcp-server.php`**
@@ -167,9 +173,12 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
167
173
  - **API-style routes, JSON responses, handlers, webhooks, form-processing endpoints, `route.php`, or request validation in handlers**
168
174
  Read `route-handlers.md`
169
175
 
170
- - **Swagger or OpenAPI generation, `swaggerDocs`, `pphp-swagger.json`, `create-swagger-docs`, or `settings/prisma-schema-config.json`**
176
+ - **Swagger or OpenAPI generation, `swaggerDocs`, generated per-model swagger docs, `create-swagger-docs`, or `settings/prisma-schema-config.json`**
171
177
  Read `swagger-docs.md`
172
178
 
179
+ - **Writing or running app tests, PHPUnit, the root `tests/` directory, `npm run test`, or verifying a change with the test suite**
180
+ Read `testing.md`, then the project's `tests/README.md`
181
+
173
182
  - **Upgrading Prisma PHP, enabling features, syncing framework-managed project files, or running project updates**
174
183
  Read `upgrading.md`
175
184
 
@@ -202,6 +211,7 @@ The current Prisma PHP docs shipped here include:
202
211
  - `pulsepoint.md`
203
212
  - `route-handlers.md`
204
213
  - `swagger-docs.md`
214
+ - `testing.md`
205
215
  - `typescript.md`
206
216
  - `upgrading.md`
207
217
  - `validator.md`
@@ -211,7 +221,7 @@ This inventory exists to help AI find the right Prisma PHP guidance quickly. It
211
221
 
212
222
  When a task depends on optional capabilities such as `backendOnly`, `swaggerDocs`, `typescript`, `websocket`, or `mcp`, inspect `./prisma-php.json` before assuming the generated scaffold exists.
213
223
 
214
- When adding or reviewing AI guidance, do not stop at older docs only. Make sure the guidance also covers `backend-only.md`, `email.md`, `env.md`, `get-started-ia.md`, `mcp.md`, `swagger-docs.md`, `typescript.md`, and `websocket.md`, plus newer behavior documented in `fetching-data.md` and `metadata-and-og-images.md`.
224
+ When adding or reviewing AI guidance, do not stop at older docs only. Make sure the guidance also covers `backend-only.md`, `email.md`, `env.md`, `get-started-ia.md`, `mcp.md`, `swagger-docs.md`, `typescript.md`, and `websocket.md`, plus newer behavior documented in `fetching-data.md`, `metadata-and-og-images.md`, and `testing.md`.
215
225
 
216
226
  ## Framework-generated files
217
227
 
@@ -232,8 +242,10 @@ When organizing a growing Prisma PHP app, keep route code and reusable code sepa
232
242
  - keep `src/app` focused on the route tree, route-local layouts, pages, handlers, and route-scoped partials
233
243
  - prefer `src/Components` for reusable application UI components shared across multiple routes or layouts
234
244
  - keep reusable non-UI code such as services, auth, middleware, Prisma classes, and helper libraries in `src/Lib`
245
+ - treat route-private folders such as `src/app/<route>/_components` as an implementation detail for files that stay owned by that route only
235
246
  - treat generated libraries such as `src/Lib/PHPXUI` and `src/Lib/PPIcons` as library-specific surfaces governed by their manifests and matching `.github/instructions/**/*.instructions.md` files
236
247
  - if a partial starts in `src/app` but becomes shared across the app, promote it into `src/Components`
248
+ - do **not** default to creating `src/app/<route>/_components` for app-owned section components such as `HeroSection`, `FormSection`, or `SidebarSection`; prefer `src/Components` unless the user explicitly wants route-local colocation and the files are truly private to that route
237
249
  - do **not** default to placing app-wide reusable components under `src/app` unless the user explicitly wants route-local colocation
238
250
 
239
251
  ## HTML-first component tag contract
@@ -306,15 +318,18 @@ When a task involves Prisma PHP CLI usage, keep the command guidance aligned wit
306
318
 
307
319
  For normal full-stack Prisma PHP work, assume the user wants the PulsePoint-first approach unless they explicitly ask otherwise.
308
320
 
309
- PulsePoint is the primary JavaScript authoring model for frontend work in Prisma PHP. For normal page behavior, keep the client logic inside a plain inline `<script>` within the route or imported-partial root, let Prisma PHP scope and execute it, and prefer `pp.fetchFunction(...)` over ad hoc endpoints.
321
+ PulsePoint is the primary JavaScript authoring model for frontend work in Prisma PHP. For normal page behavior, keep the client logic inside a plain inline `<script>` within the route or imported-partial root, let Prisma PHP scope and execute it, and prefer `pp.rpc(...)` over ad hoc endpoints.
310
322
 
311
323
  Default interaction stack:
312
324
 
313
325
  1. render route UI with `index.php`
314
326
  2. keep browser-side interactivity in PulsePoint
315
- 3. call backend PHP from the frontend with `pp.fetchFunction(...)`
327
+ 3. call backend PHP from the frontend with `pp.rpc(...)`
316
328
  4. mark callable PHP functions or methods with `#[Exposed]`
317
329
  5. validate and normalize input on the PHP side with `PP\Validator`
330
+ 6. use `pp.socket(...)` (named sockets) only when the flow is genuinely long-lived and bidirectional — chat, presence, live feeds
331
+
332
+ `pp.rpc(...)` is the runtime RPC API. Framework-level RPC failures (unknown function, auth, roles, CSRF, origin, rate limit, server error) arrive as HTTP error statuses with an `{"error": "..."}` body and **reject** the `pp.rpc(...)` promise, so wrap calls in `try/catch` when the UI reacts to failures. Routine, expected validation feedback should still be returned as structured data (`success`, `errors`, normalized values), not thrown.
318
333
 
319
334
  Treat this as the default for:
320
335
 
@@ -336,7 +351,7 @@ Do **not** default to:
336
351
  - a PHP-only interaction style
337
352
  - plain browser-DOM wiring when PulsePoint state, bindings, and native `on*` handlers already fit the task
338
353
  - ad hoc `fetch('/api/...')` patterns
339
- - extra `route.php` files for page-local interactions that already fit `pp.fetchFunction(...)`
354
+ - extra `route.php` files for page-local interactions that already fit `pp.rpc(...)`
340
355
  - a separate Node realtime or tool server when the documented Prisma PHP runtime already fits the task
341
356
 
342
357
  Choose a more PHP-only or handler-only pattern only when:
@@ -364,7 +379,7 @@ Also follow these route-file rules:
364
379
  - `index.php` and nested `layout.php` must render a single parent HTML element
365
380
  - use that single parent element as the route boundary; if the visible content should stay inside a semantic element such as `<main>`, `<section>`, or `<article>`, wrap it in a neutral parent such as `<div>`
366
381
  - for normal pages and nested layouts, do **not** manually author `pp-component` on that root; Prisma PHP adds it automatically
367
- - author a plain `<script>` tag inside that root when PulsePoint logic is needed and do **not** add `type="text/pp"` manually
382
+ - author a plain `<script>` tag inside that root when PulsePoint logic is needed and do **not** put any `type` attribute on it — the runtime only recognizes untyped component scripts
368
383
  - keep the `<script>` as the last child of the route boundary, usually as a sibling of the visible content container instead of nesting it inside the semantic content element by default
369
384
  - do **not** leave the `<script>` outside the route boundary
370
385
  - write PulsePoint state, derived values, and functions directly at the top level of that script; do **not** wrap them in `DOMContentLoaded`, an IIFE, manual `pp.mount()` calls, or custom scoping helpers
@@ -424,7 +439,7 @@ Do not:
424
439
 
425
440
  - put a sibling `<script>` next to a route root or imported partial root
426
441
  - manually add `pp-component` inside imported partial source
427
- - manually add `type="text/pp"` to route or imported-partial scripts
442
+ - add any `type` attribute to route or imported-partial component scripts
428
443
  - wrap imported-partial PulsePoint code in `DOMContentLoaded`, an IIFE, manual `pp.mount()` calls, or custom auto-execute helpers
429
444
 
430
445
  ## Metadata rules
@@ -440,19 +455,19 @@ Important metadata rules:
440
455
 
441
456
  ## Streaming and SSE rules
442
457
 
443
- Prisma PHP supports streaming through `pp.fetchFunction(...)` when an exposed function yields values.
458
+ Prisma PHP supports streaming through `pp.rpc(...)` when an exposed function yields values.
444
459
 
445
460
  Default streaming rules:
446
461
 
447
462
  - prefer an exposed generator that simply yields strings or arrays
448
- - let Prisma PHP handle the SSE response automatically for normal `pp.fetchFunction(...)` streaming
463
+ - let Prisma PHP handle the SSE response automatically for normal `pp.rpc(...)` streaming
449
464
  - on the client, put stream UI updates in `onStream`, `onStreamError`, and `onStreamComplete`
450
465
  - do not wait for a final JSON payload when the response is streamed
451
466
 
452
467
  Current parsing rules AI should know:
453
468
 
454
469
  - Prisma PHP sends streamed payloads as SSE `data:` lines
455
- - the built-in `pp.fetchFunction(...)` stream parser currently forwards only `data:` lines to `onStream`
470
+ - the built-in `pp.rpc(...)` stream parser currently forwards only `data:` lines to `onStream`
456
471
  - `event:`, `id:`, and `retry:` may be emitted by low-level SSE helpers, but the built-in stream callback currently ignores them
457
472
  - prefer JSON values or single-line strings for streamed chunks instead of multi-line text blobs
458
473
 
@@ -481,7 +496,7 @@ Important: creating a route means creating or updating the correct folder and ro
481
496
  - use `error.php` for route or app-level error UI
482
497
  - use `loading.php` when the task is specifically about a loading UI state for a route subtree
483
498
 
484
- For normal route-local interactivity, prefer `index.php` plus PulsePoint and `pp.fetchFunction(...)` over inventing extra handlers.
499
+ For normal route-local interactivity, prefer `index.php` plus PulsePoint and `pp.rpc(...)` over inventing extra handlers.
485
500
 
486
501
  In a consumer app, also verify `backendOnly` in `prisma-php.json`:
487
502
 
@@ -516,6 +531,7 @@ Use this auth decision flow:
516
531
 
517
532
  Important auth rules:
518
533
 
534
+ - the auth classes are app-owned files under `src/Lib/Auth` in the `Lib\Auth` namespace — write `use Lib\Auth\Auth;` and `use Lib\Auth\AuthConfig;`, never `PP\Auth\...`
519
535
  - route privacy strategy is configured from `AuthConfig.php`
520
536
  - Prisma PHP supports both public-default and private-default route protection strategies
521
537
  - Prisma PHP defaults to public routes, so keep the public-default strategy when the app will expose many public pages
@@ -610,26 +626,34 @@ Important env rules:
610
626
 
611
627
  ## WebSocket rules
612
628
 
613
- When the task involves realtime messaging, presence, live dashboards, `Ratchet`, or browser `WebSocket`, read `websocket.md` first.
629
+ When the task involves realtime messaging, presence, live dashboards, chat, `pp.socket(...)`, or `Ratchet`, read `websocket.md` first.
614
630
 
615
- Prisma PHP websocket support follows a Ratchet-based PHP server plus a `ConnectionManager` under `src/Lib/Websocket`. Do not replace that default with Socket.IO, a separate Node server, or an unrelated hosted realtime service unless the user explicitly asks for a different architecture.
631
+ Prisma PHP realtime support is built on **named sockets**: `pp.socket(name, args, handlers)` in the browser, and a Ratchet-based server under `src/Lib/Websocket` that dispatches each connection to a handler registered with `SocketRegistry`. Do not replace that default with Socket.IO, a separate Node server, raw `new WebSocket(...)` wiring, or an unrelated hosted realtime service unless the user explicitly asks for a different architecture.
616
632
 
617
633
  Use this websocket workflow:
618
634
 
619
635
  1. read `websocket.md`
620
636
  2. inspect whether websocket support is enabled in `prisma-php.json` in the target app
621
- 3. inspect `src/Lib/Websocket`
622
- 4. inspect the route or client script that opens the browser `WebSocket`
637
+ 3. inspect `src/Lib/Websocket`, especially `sockets.php` for the registered socket names
638
+ 4. inspect the route script that calls `pp.socket(...)`
623
639
  5. inspect `settings/restart-websocket.ts` when local restart behavior matters
624
640
  6. inspect framework internals only when the docs do not answer the task
625
641
 
626
642
  Important websocket rules:
627
643
 
644
+ - connect from the browser with `pp.socket(name, args, handlers)`; do **not** generate raw `new WebSocket(...)` wiring for app realtime work
645
+ - register server handlers with `SocketRegistry::register(...)` in `src/Lib/Websocket/sockets.php`; socket names are unique application-wide
646
+ - do not put socket handlers in route files — route files are not loaded by the socket server process
647
+ - keep the wire contract intact: one endpoint (`/__pulsepoint/ws`), the function named in the `name` query parameter, arguments as the connection's first JSON frame, one JSON value per frame in either direction, and `{"error": "..."}` (that key alone) reserved for failures
628
648
  - use `src/Lib/Websocket/websocket-server.php` as the source of truth for startup behavior
629
- - use `src/Lib/Websocket/ConnectionManager.php` as the lifecycle boundary for clients and broadcasts
630
- - preserve documented env vars and defaults: `WS_NAME`, `WS_VERSION`, `WS_HOST`, `WS_PORT`, `WS_VERBOSE`, `APP_TIMEZONE`
649
+ - use `src/Lib/Websocket/ConnectionManager.php` as the wire and lifecycle boundary (handshake security, argument frame, dispatch, limits)
650
+ - use `SocketPool` for broadcasts; keep authenticated and guest traffic in separate pools
651
+ - declare auth with `requireAuth` / `allowedRoles` at registration; the handshake is verified against the JWT auth cookie before the handler runs
652
+ - a `Socket::send(...)` that returns `false` means the browser is gone — stop sending, it is not an error
653
+ - preserve documented env vars and defaults: `WS_NAME`, `WS_VERSION`, `WS_HOST`, `WS_PORT`, `WS_VERBOSE`, `APP_TIMEZONE`, `MAX_WEBSOCKET_CONNECTIONS`, `MAX_WEBSOCKET_MESSAGE_BYTES`, `MAX_WEBSOCKET_MESSAGES_PER_WINDOW`, `WEBSOCKET_RATE_WINDOW_SECONDS`, `WEBSOCKET_IDLE_TIMEOUT_SECONDS`, `WEBSOCKET_ALLOWED_ORIGINS`
631
654
  - preserve CLI overrides through `--host=...`, `--port=...`, and `--verbose=...`
632
655
  - preserve the documented casing `src/Lib/Websocket`
656
+ - in development, `settings/bs-config.ts` proxies `/__pulsepoint/ws` from the BrowserSync origin to the Ratchet server, so `pp.socket(...)` needs no `url` option; pass `url` only outside that proxy
633
657
  - for existing apps, enable `websocket` in `prisma-php.json` and run `npx pp update project -y` before inventing manual scaffolding
634
658
 
635
659
  ## MCP rules
@@ -681,12 +705,15 @@ Important ORM rules:
681
705
 
682
706
  ## Validation rules
683
707
 
684
- When a task involves user input, form handling, search params, JSON payloads, `pp.fetchFunction(...)`, `route.php` bodies, or tool parameters, do not trust raw values.
708
+ When a task involves user input, form handling, search params, JSON payloads, `pp.rpc(...)`, `route.php` bodies, or tool parameters, do not trust raw values.
685
709
 
686
710
  Default Prisma PHP validation rules:
687
711
 
688
712
  - use `PP\Validator` as the backend validation and normalization layer
689
713
  - prefer the `Rule` builder for rule-based validation
714
+ - start `Rule` builders with `Rule::required()`, `Rule::optional()`, or `Rule::make()`
715
+ - chain rule methods such as `->min(...)`, `->max(...)`, `->email()`, and `->regex(...)` on that builder instance
716
+ - do **not** generate static calls such as `Rule::max(80)`; for optional constrained fields use `Rule::optional()->max(80)` or `Rule::make()->max(80)`
690
717
  - validate in PHP even when the frontend already performs local checks
691
718
  - return structured validation results for expected failures
692
719
  - do not treat routine invalid input as an uncaught exception
@@ -696,6 +723,7 @@ When internals matter, the documented Prisma PHP core validator location is:
696
723
 
697
724
  ```txt
698
725
  vendor/tsnc/prisma-php/src/Validator.php
726
+ vendor/tsnc/prisma-php/src/Rule.php
699
727
  ```
700
728
 
701
729
  ## PulsePoint rules
@@ -706,13 +734,15 @@ Also follow these rules:
706
734
 
707
735
  - treat PulsePoint as the primary JavaScript authoring model for normal full-stack frontend work
708
736
  - keep page and imported-partial client logic inside the boundary's plain `<script>` tag instead of building extra DOM-ready or self-executing wrappers
709
- - prefer `pp.fetchFunction(...)` over ad hoc `fetch('/api/...')` calls for page-local PHP interactions
737
+ - prefer `pp.rpc(...)` over ad hoc `fetch('/api/...')` calls for page-local PHP interactions
710
738
  - reserve plain browser JavaScript outside PulsePoint for external libraries, low-level browser APIs, and reusable helpers in `ts/`
711
739
  - do not invent undocumented PulsePoint helpers or directives
712
740
  - do not write React, Vue, Alpine, or Livewire syntax and call it PulsePoint
713
741
  - keep backend concerns separate from PulsePoint runtime concerns
714
742
  - prefer simple documented runtime primitives over abstractions copied from other ecosystems
715
- - use `pp-style` for template-driven inline CSS and plain `style` for fully static inline CSS
743
+ - do not treat app-registered helpers such as `twMerge(...)` as PulsePoint built-ins; route those tasks through the Tailwind-enabled Prisma PHP docs after checking feature flags
744
+ - use `pp-style` whenever inline CSS contains `{...}` interpolation or any other template-driven/reactive value, and reserve plain `style` for fully static inline CSS
745
+ - do **not** generate reactive inline CSS inside a plain `style` attribute such as `style="width: {progress}%";` use `pp-style="width: {progress}%";` instead so source markup stays editor-friendly
716
746
  - use `pp-spread="{...attrs}"` for dynamic attribute objects and omit nullish values from those objects
717
747
  - use `pp-for` only on `<template>` with `item in items` or `(item, index) in items`
718
748
  - use plain `key` for keyed diffing; do not invent `pp-key`
@@ -730,6 +760,8 @@ Also follow these rules:
730
760
  - use kebab-case component attributes and rely on the runtime to hydrate camelCase PHPX properties and PulsePoint props
731
761
  - keep component file names and class names aligned
732
762
  - preserve documented PHPX patterns for `$props`, `$children`, `$class`, and `getAttributes(...)`
763
+ - in Tailwind-enabled apps, use `getMergeClasses(...)` and `PP\PHPX\TwMerge::merge(...)` as emitters of frontend `twMerge(...)` expressions instead of finalizing Tailwind class conflicts in PHP
764
+ - when a route or imported partial needs direct Tailwind-aware class composition, treat `twMerge(...)` as an app-level browser helper available only when `tailwindcss` is enabled
733
765
  - follow documented component placement and grouping conventions before inspecting framework internals
734
766
 
735
767
  ## When to inspect framework internals
@@ -740,6 +772,8 @@ Useful app-mode core locations include:
740
772
 
741
773
  ```txt
742
774
  vendor/tsnc/prisma-php/src
775
+ vendor/tsnc/prisma-php/src/PHPX/PHPX.php
776
+ vendor/tsnc/prisma-php/src/PHPX/TwMerge.php
743
777
  vendor/tsnc/prisma-php/src/PHPX/TemplateCompiler.php
744
778
  vendor/tsnc/prisma-php/src/ImportComponent.php
745
779
  vendor/tsnc/prisma-php/src/MainLayout.php