prisma-php 0.0.1

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.
@@ -0,0 +1,280 @@
1
+ ---
2
+ title: Authentication
3
+ description: Learn how Prisma PHP authentication works so AI agents can generate route protection, sessions, RBAC, credentials auth, and social auth code using the documented framework model.
4
+ related:
5
+ title: Related docs
6
+ description: Read the official Prisma PHP authentication docs before generating or editing auth code.
7
+ links:
8
+ - /docs/auth-get-started
9
+ - /docs/credentials
10
+ - /docs/state-manager-auth
11
+ - /docs/fetch-function
12
+ - /docs/route-php
13
+ - /docs/php-validator
14
+ ---
15
+
16
+ Prisma PHP authentication should be implemented from the documented Prisma PHP auth model, not from assumptions copied from Laravel guards, NextAuth, Passport, Sanctum, or generic custom JWT middleware.
17
+
18
+ If a task involves login, registration, route protection, role checks, route privacy defaults, session payload updates, credentials auth, OAuth providers, or auth-aware frontend interactions, AI agents should read the relevant auth docs first and keep the implementation aligned with the installed Prisma PHP version.
19
+
20
+ ## AI rule: read the auth docs first
21
+
22
+ Before generating, editing, or reviewing auth-related code, use this order:
23
+
24
+ 1. Read `./prisma-php.json`.
25
+ 2. Read the installed local auth docs in `node_modules/prisma-php/dist/docs`.
26
+ 3. Read this `authentication.md` file.
27
+ 4. Inspect `src/Lib/Auth/AuthConfig.php` when present.
28
+ 5. Inspect the current auth-related route tree under `src/app`.
29
+ 6. Inspect the Prisma schema and generated ORM classes if the auth flow reads or writes users.
30
+ 7. Inspect Prisma PHP core internals only when the docs do not answer the task.
31
+
32
+ Do not assume another framework’s auth abstractions apply directly.
33
+
34
+ ## Read this doc when you need
35
+
36
+ - **route privacy defaults, `AuthConfig.php`, JWT session lifecycle, `Auth::signIn(...)`, `Auth::signOut(...)`, `refreshUserSession(...)`, route RBAC, or provider overview** → official `auth-get-started`
37
+ - **email/password registration, login, password hashing, CSRF-aware credential flow, or user/role schema design** → official `credentials`
38
+ - **social login, provider credentials, callback route handling, account linking, or OAuth account schema** → official `state-manager-auth`
39
+
40
+ ## Core auth model AI should follow
41
+
42
+ Prisma PHP documents authentication around a central auth configuration plus framework-managed session handling.
43
+
44
+ The official docs describe these major concepts:
45
+
46
+ - `AuthConfig.php` is the central place for defining route protection strategy and role-based route rules
47
+ - sessions are managed through Prisma PHP auth helpers rather than ad hoc cookie code
48
+ - `Auth::signIn(...)` creates the session payload
49
+ - `Auth::signOut(...)` ends the session and can redirect
50
+ - `refreshUserSession(...)` updates the active session payload when user permissions or profile data change
51
+ - route-level RBAC and function-level access control are separate but complementary concerns
52
+
53
+ ## Security strategy
54
+
55
+ Prisma PHP supports two top-level route privacy strategies in `src/Lib/Auth/AuthConfig.php`.
56
+
57
+ ### 1. Opt-in privacy (public by default)
58
+
59
+ Use this model when most routes are public and only a few pages should require login.
60
+
61
+ Typical fit:
62
+
63
+ - marketing sites
64
+ - blogs
65
+ - public directories with a small private dashboard
66
+
67
+ Mental model:
68
+
69
+ - routes are public by default
70
+ - specific private routes are listed explicitly
71
+
72
+ ### 2. Opt-out privacy (private by default)
73
+
74
+ Use this model when most routes should require authentication and only a few entry points are public.
75
+
76
+ Typical fit:
77
+
78
+ - SaaS dashboards
79
+ - admin panels
80
+ - internal applications
81
+
82
+ Mental model:
83
+
84
+ - routes are private by default
85
+ - specific public routes are whitelisted explicitly
86
+
87
+ ## Auth lifecycle
88
+
89
+ ### Sign in
90
+
91
+ Use `Auth::signIn(...)` after credentials or provider identity are validated.
92
+
93
+ The session payload should contain the user data your app needs for identity and authorization decisions, commonly including:
94
+
95
+ - `id`
96
+ - `role`
97
+
98
+ Do not invent a separate session writer when the framework already documents `Auth::signIn(...)`.
99
+
100
+ ### Sign out
101
+
102
+ Use `Auth::signOut(...)` to destroy the session and invalidate the client cookie.
103
+
104
+ When the flow needs a post-logout redirect, use the documented redirect argument instead of custom manual cookie clearing.
105
+
106
+ ### Live session refresh
107
+
108
+ Use `refreshUserSession(...)` when a currently signed-in user’s auth payload must change immediately, such as:
109
+
110
+ - role promotion or demotion
111
+ - profile data updates included in the auth payload
112
+ - account status changes that should take effect without forcing a new login
113
+
114
+ Do not force logout/login loops for cases the framework already handles with a silent session refresh.
115
+
116
+ ## Access control model
117
+
118
+ Prisma PHP has at least two auth protection layers that AI should keep separate.
119
+
120
+ ### Route-level protection
121
+
122
+ Use auth config to protect entire routes or route groups.
123
+
124
+ This is the right place for:
125
+
126
+ - dashboard-only pages
127
+ - admin sections
128
+ - authenticated profile/account pages
129
+ - public route allowlists in private-default apps
130
+
131
+ ### Function-level protection
132
+
133
+ Use `#[Exposed(allowedRoles: [...])]` when frontend code calls PHP functions directly and specific roles must be enforced at the function boundary.
134
+
135
+ This is the right place for:
136
+
137
+ - destructive admin-only actions
138
+ - privileged inline mutations
139
+ - page-local operations triggered from PulsePoint UIs
140
+
141
+ Do not rely only on frontend hiding or route visibility when a backend callable function still needs authorization.
142
+
143
+ ## Role model
144
+
145
+ The official auth docs describe roles as type-safe and defined in auth configuration.
146
+
147
+ AI should preserve the project’s existing role vocabulary and avoid inventing mixed casing or alternate role names unless the user explicitly asks for them.
148
+
149
+ Examples commonly shown in docs:
150
+
151
+ - `Admin`
152
+ - `User`
153
+
154
+ When backend functions are protected with `#[Exposed(allowedRoles: [...])]`, keep those role names aligned with the same project role model.
155
+
156
+ ## Credentials authentication
157
+
158
+ The credentials docs describe the classic email/password flow as a full-stack Prisma PHP pattern where backend logic and form UI can live together in route files.
159
+
160
+ ### Schema expectations
161
+
162
+ For credentials auth, the docs show a user model with fields such as:
163
+
164
+ - `email`
165
+ - `password`
166
+ - `emailVerified`
167
+ - role relation fields
168
+
169
+ The example also includes a `UserRole` model so role names can support RBAC-oriented auth flows.
170
+
171
+ ### Registration pattern
172
+
173
+ The documented registration flow uses:
174
+
175
+ - a route such as `src/app/auth/register/index.php`
176
+ - `#[Exposed]` to allow the frontend to call the PHP function directly
177
+ - validation and normalization before persistence
178
+ - password hashing before storing the user
179
+ - a redirect to the login page after successful registration
180
+
181
+ ### Login pattern
182
+
183
+ The documented login flow uses:
184
+
185
+ - a route such as `src/app/auth/login/index.php`
186
+ - a user lookup through Prisma ORM
187
+ - `password_verify(...)` for password comparison
188
+ - `Auth::signIn(...)` with the session payload
189
+ - a redirect after successful sign-in
190
+
191
+ ### Validation rule
192
+
193
+ When generating credentials auth, do not trust raw request data.
194
+
195
+ For backend validation and normalization, default to Prisma PHP’s validation layer rather than browser-only checks. In this docs set, that means using the documented validation guidance alongside `PP\Validator`-style server validation patterns from the rest of the local docs.
196
+
197
+ ## Social authentication
198
+
199
+ The social auth docs describe provider-based authentication using framework helpers and provider classes.
200
+
201
+ ### Schema expectations
202
+
203
+ For provider auth, the docs show:
204
+
205
+ - a `User` model
206
+ - an `Account` model that stores provider identity and tokens
207
+ - a unique provider/provider-account pairing
208
+
209
+ This means AI should not generate social auth code without also checking whether the schema already supports provider accounts.
210
+
211
+ ### Environment credentials
212
+
213
+ Provider credentials belong in `.env` using provider-specific auth keys.
214
+
215
+ Do not hardcode provider secrets in route files.
216
+
217
+ ### Callback route pattern
218
+
219
+ The docs describe a dynamic auth handler route that handles both login redirection and callback processing.
220
+
221
+ Keep the documented route pattern instead of inventing custom callback plumbing.
222
+
223
+ ## Prisma ORM workflow for auth tasks
224
+
225
+ When the task involves auth schema updates, do not confuse ORM changes with project updates.
226
+
227
+ Use this order:
228
+
229
+ 1. update `prisma/schema.prisma` as needed
230
+ 2. run `npx prisma migrate dev` when the schema changes and the database must be updated
231
+ 3. run `npx ppo generate` so generated PHP ORM classes match the schema
232
+ 4. then implement the PHP auth flow that depends on those classes
233
+
234
+ Do **not** use `npx pp update project -y` as the default response to auth schema changes.
235
+
236
+ ## Route placement guidance
237
+
238
+ Common auth route examples from the official docs include:
239
+
240
+ - `src/app/auth/register/index.php`
241
+ - `src/app/auth/login/index.php`
242
+ - a dynamic provider callback route under an auth-related segment
243
+
244
+ If the user asks for a normal auth page, prefer `index.php`.
245
+
246
+ If the user asks for a direct callback or handler-only route, use the documented dynamic auth handler pattern.
247
+
248
+ ## PulsePoint and auth
249
+
250
+ When auth UI is interactive, Prisma PHP’s normal full-stack pattern still applies:
251
+
252
+ - use PulsePoint for local reactive state and UI feedback
253
+ - use `pp.fetchFunction(...)` when the page should call PHP directly
254
+ - expose callable PHP functions with `#[Exposed]`
255
+ - enforce final validation and authorization on the PHP side
256
+
257
+ Do not replace the documented Prisma PHP auth flow with a custom SPA-only auth architecture unless the user explicitly wants a different design.
258
+
259
+ ## AI rules for auth tasks
260
+
261
+ - read the auth docs before generating auth code
262
+ - do not invent custom middleware layers when `AuthConfig.php` already defines route protection strategy
263
+ - do not invent alternate session storage when the framework already provides documented auth helpers
264
+ - do not skip schema review for credentials or provider-based auth
265
+ - do not hardcode provider secrets in source code
266
+ - do not rely on frontend checks as the final authorization layer
267
+ - keep route-level protection and function-level protection distinct
268
+ - keep role names aligned with the project’s actual role model
269
+ - when using `#[Exposed]`, add role restrictions for privileged actions when required
270
+ - when schema changes are required, migrate first and generate PHP classes second
271
+
272
+ ## Suggested file name
273
+
274
+ Use this file name:
275
+
276
+ ```txt
277
+ authentication.md
278
+ ```
279
+
280
+ It is clear, predictable, and consistent with the existing local docs such as `components.md`, `fetching-data.md`, and `route-handlers.md`.
@@ -0,0 +1,346 @@
1
+ ---
2
+ title: Caching
3
+ description: Learn how to cache pages and responses in Prisma PHP with `CacheHandler`, when to invalidate cached output, and when AI agents should inspect the core cache class for framework-level decisions.
4
+ related:
5
+ title: Next Steps
6
+ description: Learn more about the Prisma PHP cache APIs and route-level cache control.
7
+ links:
8
+ - /docs/cache-handler
9
+ - /docs/index-php
10
+ - /docs/route-php
11
+ - /docs/pages-and-layouts
12
+ ---
13
+
14
+ Caching is a technique for storing the result of work so that future requests can be served faster without repeating the same database queries and rendering logic.
15
+
16
+ In Prisma PHP, caching is documented around **`CacheHandler`**, which provides a **file-based cache layer** that can serve **static HTML snapshots** to reduce TTFB (Time To First Byte). Unlike Next.js Cache Components, Prisma PHP’s documented cache model is not based on `use cache`, Suspense streaming, or partial prerendering. It is based on environment settings, route-level overrides, and explicit cache invalidation.
17
+
18
+ ## AI rule: read the cache docs first
19
+
20
+ Before generating, editing, or reviewing Prisma PHP cache-related code, use this order:
21
+
22
+ 1. Read `./prisma-php.json`.
23
+ 2. Read the installed local docs in `node_modules/prisma-php/dist/docs`.
24
+ 3. Read this `caching.md` file.
25
+ 4. Inspect the current route tree under `src/app`.
26
+ 5. Inspect nearby mutation flows that may need cache invalidation.
27
+ 6. Inspect Prisma PHP core internals only when the docs do not answer the task clearly.
28
+
29
+ Do not assume Next.js, Laravel response cache packages, Symfony HTTP cache, or generic PSR cache habits map directly to Prisma PHP.
30
+
31
+ ## Where the core cache file lives
32
+
33
+ The Prisma PHP cache core file lives in:
34
+
35
+ ```txt
36
+ vendor/tsnc/prisma-php/src/CacheHandler.php
37
+ ```
38
+
39
+ This file is useful when AI needs to make a **more detailed framework-level decision** that is not already answered by the installed docs.
40
+
41
+ Examples:
42
+
43
+ - confirming the exact available methods and property names
44
+ - verifying how TTL fallback is resolved internally
45
+ - checking how cache files are named or mapped to URIs
46
+ - understanding how route invalidation is normalized
47
+ - verifying write behavior, locking, and file-system assumptions
48
+ - debugging framework-level cache behavior that looks inconsistent with the docs
49
+
50
+ For normal app work, prefer the docs first and inspect `CacheHandler.php` only when the task depends on internal behavior.
51
+
52
+ ## Cache decision flow for AI agents
53
+
54
+ When a task mentions caching, use this decision flow:
55
+
56
+ 1. identify whether the route is a rendered page or a direct handler
57
+ 2. decide whether the output is stable enough to cache safely
58
+ 3. check whether the task needs a global default or a route-level override
59
+ 4. identify which writes or mutations should invalidate cached routes
60
+ 5. inspect `CacheHandler.php` only if the docs and current project code still leave important behavior unclear
61
+
62
+ This keeps AI aligned with documented Prisma PHP behavior instead of inventing cache abstractions from other ecosystems.
63
+
64
+ ## How Prisma PHP caching works
65
+
66
+ Prisma PHP determines whether to cache a route using the interaction between:
67
+
68
+ - global `.env` settings
69
+ - route-level `CacheHandler` overrides
70
+
71
+ The docs describe this as a caching logic matrix:
72
+
73
+ - if `CACHE_ENABLED="false"` and no route override is set, the route is not cached
74
+ - if `CACHE_ENABLED="false"` and `CacheHandler::$isCacheable = true`, caching is forced for that route
75
+ - if `CACHE_ENABLED="true"` and no route override is set, caching applies by default
76
+ - if `CACHE_ENABLED="true"` and `CacheHandler::$isCacheable = false`, that route is skipped from caching
77
+
78
+ This means Prisma PHP gives you both a **global cache default** and a **per-route escape hatch**.
79
+
80
+ ## Global configuration
81
+
82
+ Prisma PHP documents cache defaults through your `.env` file.
83
+
84
+ ```env filename=".env"
85
+ # Enable system-wide caching
86
+ CACHE_ENABLED="true"
87
+
88
+ # Default TTL (600 = 10 minutes)
89
+ CACHE_TTL="600"
90
+ ```
91
+
92
+ According to the docs, `CACHE_ENABLED` controls whether caching is enabled by default, and `CACHE_TTL` sets the default TTL in seconds.
93
+
94
+ ## Route-level overrides
95
+
96
+ You can override cache behavior for a specific route in the route entry file or controller logic.
97
+
98
+ ```php filename="src/app/blog/index.php"
99
+ <?php
100
+
101
+ use PP\CacheHandler;
102
+
103
+ // Force cache this specific page
104
+ CacheHandler::$isCacheable = true;
105
+
106
+ // Set a custom TTL in seconds
107
+ CacheHandler::$ttl = 10;
108
+ ?>
109
+ ```
110
+
111
+ The docs show `CacheHandler::$isCacheable` for opting a route into or out of caching and `CacheHandler::$ttl` for overriding the default TTL for that route.
112
+
113
+ ## What gets cached
114
+
115
+ The Prisma PHP docs describe `CacheHandler` as a way to **bypass database queries and view rendering logic by serving static HTML snapshots**. This means the primary documented cache target is the final rendered output for a route, stored as files on disk.
116
+
117
+ This is the main Prisma PHP equivalent to route-level page caching.
118
+
119
+ ## Serving cached content
120
+
121
+ The documented API includes:
122
+
123
+ ```php
124
+ CacheHandler::serveCache(string $uri, int $defaultTtl = 600): void
125
+ ```
126
+
127
+ According to the docs, this method attempts to serve a static file for the given URI. If a valid, non-expired cache file exists, it outputs the content and terminates script execution. The docs also note that it checks route-specific TTL first, falls back to the default TTL if no route config exists, and appends an HTML comment showing when the cached copy was generated.
128
+
129
+ ## Basic page-caching example
130
+
131
+ A typical Prisma PHP page-caching pattern looks like this:
132
+
133
+ ```php filename="src/app/blog/index.php"
134
+ <?php
135
+
136
+ use PP\CacheHandler;
137
+ use Lib\Prisma\Classes\Prisma;
138
+
139
+ // Mark this route as cacheable
140
+ CacheHandler::$isCacheable = true;
141
+
142
+ // Optional route-specific TTL
143
+ CacheHandler::$ttl = 600;
144
+
145
+ $prisma = Prisma::getInstance();
146
+
147
+ $posts = $prisma->post->findMany([
148
+ 'orderBy' => [
149
+ 'createdAt' => 'desc',
150
+ ],
151
+ ]);
152
+
153
+ ?>
154
+
155
+ <ul>
156
+ <?php foreach ($posts as $post): ?>
157
+ <li><?= htmlspecialchars($post['title']) ?></li>
158
+ <?php endforeach; ?>
159
+ </ul>
160
+ ```
161
+
162
+ This is the Prisma PHP equivalent of caching a page’s rendered result rather than caching a React component tree.
163
+
164
+ ## Invalidating cache by route
165
+
166
+ Prisma PHP documents URI-based invalidation through:
167
+
168
+ ```php
169
+ CacheHandler::invalidateByUri(string|array $uris): void
170
+ ```
171
+
172
+ This method removes cache files for one or more specific routes. The docs note that it accepts leading slashes or plain paths.
173
+
174
+ Example:
175
+
176
+ ```php filename="src/app/blog/_lib/save-post.php"
177
+ <?php
178
+
179
+ use PP\CacheHandler;
180
+
181
+ // Invalidate one route
182
+ CacheHandler::invalidateByUri('/blog');
183
+
184
+ // Invalidate multiple routes
185
+ CacheHandler::invalidateByUri([
186
+ '/',
187
+ '/blog',
188
+ '/dashboard',
189
+ ]);
190
+ ```
191
+
192
+ This is the core Prisma PHP pattern for keeping cached pages fresh after content changes.
193
+
194
+ ## Resetting cache
195
+
196
+ The docs also describe a lower-level clearing method:
197
+
198
+ ```php
199
+ CacheHandler::resetCache(?string $uri = null): void
200
+ ```
201
+
202
+ According to the docs:
203
+
204
+ - passing `null` purges all files in the cache directory
205
+ - passing a specific URI deletes the file for that route only
206
+
207
+ Example:
208
+
209
+ ```php filename="src/app/admin/route.php"
210
+ <?php
211
+
212
+ use PP\CacheHandler;
213
+
214
+ // Clear everything
215
+ CacheHandler::resetCache();
216
+
217
+ // Or clear one route
218
+ CacheHandler::resetCache('/blog');
219
+ ```
220
+
221
+ ## Content update workflow
222
+
223
+ The Prisma PHP docs explicitly recommend invalidating relevant routes after saving dynamic content so users immediately see fresh data.
224
+
225
+ Their documented example follows this pattern:
226
+
227
+ 1. save to the database
228
+ 2. invalidate the related cache URIs
229
+
230
+ Example:
231
+
232
+ ```php filename="src/app/blog/route.php"
233
+ <?php
234
+
235
+ use PP\CacheHandler;
236
+
237
+ function savePost($data)
238
+ {
239
+ // 1. Save post data
240
+ // ... database logic here ...
241
+
242
+ // 2. Invalidate affected routes
243
+ CacheHandler::invalidateByUri([
244
+ '/blog',
245
+ '/blog/recent',
246
+ ]);
247
+
248
+ return [
249
+ 'success' => true,
250
+ ];
251
+ }
252
+ ```
253
+
254
+ This is the Prisma PHP equivalent of revalidation after mutation.
255
+
256
+ ## Concurrency and writes
257
+
258
+ The docs state that `saveCache` uses `LOCK_EX` by default to prevent race conditions when two requests try to write the same cache file at the same time.
259
+
260
+ That matters most on high-traffic pages where multiple requests may attempt to generate the same cached output simultaneously.
261
+
262
+ ## Cache storage location
263
+
264
+ Prisma PHP documents cache storage at:
265
+
266
+ ```php
267
+ DOCUMENT_PATH . '/caches'
268
+ ```
269
+
270
+ The docs also note that this directory must be writable by the web server user.
271
+
272
+ ## `index.php` vs `route.php` and caching
273
+
274
+ In Prisma PHP, your cache choice still follows the route model:
275
+
276
+ - use `index.php` when caching rendered page output
277
+ - use `route.php` when caching or controlling a direct handler route
278
+ - invalidate by URI when content changes affect one or more routes
279
+
280
+ For a full-stack project, page-oriented caching will most commonly apply to `index.php` routes, since those are the normal rendered UI entry points. API-style handlers in `route.php` may also use cache logic where appropriate, but their role is different from full page rendering. This route split aligns with Prisma PHP’s documented distinction between `index.php` as the UI entry point and `route.php` as the direct handler entry point.
281
+
282
+ ## Prisma PHP vs Next.js caching mental model
283
+
284
+ If you are coming from Next.js, the closest mapping is:
285
+
286
+ | Next.js idea | Prisma PHP equivalent |
287
+ | -------------------------------------- | ------------------------------------------- |
288
+ | `use cache` on a component or function | Route/page caching with `CacheHandler` |
289
+ | revalidation after mutation | `CacheHandler::invalidateByUri(...)` |
290
+ | clearing cached output | `CacheHandler::resetCache(...)` |
291
+ | config-driven cache defaults | `.env` with `CACHE_ENABLED` and `CACHE_TTL` |
292
+
293
+ The biggest difference is that Prisma PHP’s documented model is file-based route output caching, not React component-level caching.
294
+
295
+ ## When to cache
296
+
297
+ Prisma PHP caching is especially useful for routes where:
298
+
299
+ - the rendered output is expensive to generate
300
+ - the content does not change on every request
301
+ - the same route is requested often
302
+ - you want to reduce database and rendering work
303
+
304
+ Examples:
305
+
306
+ - blog index pages
307
+ - marketing pages
308
+ - dashboards with infrequently changing summaries
309
+ - public landing pages
310
+ - documentation-style content pages
311
+
312
+ ## When not to cache aggressively
313
+
314
+ Be careful with caching routes that depend heavily on:
315
+
316
+ - per-user personalization
317
+ - rapidly changing data
318
+ - request-specific conditions
319
+ - authentication-sensitive output
320
+
321
+ In those cases, route-specific overrides or targeted invalidation are usually safer than broad default caching.
322
+
323
+ ## Practical cache design guidance
324
+
325
+ A good Prisma PHP cache decision usually looks like this:
326
+
327
+ - cache public or mostly-static rendered output
328
+ - keep TTL modest when content changes on a schedule
329
+ - invalidate specific URIs after a successful mutation
330
+ - avoid broad global resets unless the change is truly system-wide
331
+ - avoid caching personalized pages unless you are certain the output is safe to share across requests
332
+
333
+ When uncertain, prefer **targeted invalidation** over aggressive long-lived caching.
334
+
335
+ ## Good to know
336
+
337
+ - Prisma PHP’s documented cache system is `CacheHandler`.
338
+ - It is a file-based cache layer for serving static HTML snapshots.
339
+ - Global defaults are configured with `.env` using `CACHE_ENABLED` and `CACHE_TTL`.
340
+ - Per-route overrides use `CacheHandler::$isCacheable` and `CacheHandler::$ttl`.
341
+ - Route invalidation uses `CacheHandler::invalidateByUri(...)`.
342
+ - Full resets use `CacheHandler::resetCache(...)`.
343
+ - Cache files are stored in `DOCUMENT_PATH . '/caches'`.
344
+ - Cache writes use `LOCK_EX` for concurrency safety.
345
+ - The core class lives in `vendor/tsnc/prisma-php/src/CacheHandler.php`.
346
+ - Inspect the core file only when the installed docs and project code are not enough for a precise framework-level decision.