caspian-utils 0.0.11 → 0.0.12
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.
- package/dist/docs/auth.md +102 -6
- package/dist/docs/commands.md +4 -0
- package/dist/docs/index.md +1 -1
- package/dist/docs/installation.md +1 -1
- package/package.json +1 -1
package/dist/docs/auth.md
CHANGED
|
@@ -3,7 +3,7 @@ title: Authentication
|
|
|
3
3
|
description: Manage session-backed authentication in Caspian with `casp.auth`, `AuthSettings`, the global `auth` object, centralized `auth_config.py`, page decorators, RPC protection, role-based routes, and optional Google or GitHub OAuth providers.
|
|
4
4
|
related:
|
|
5
5
|
title: Related docs
|
|
6
|
-
|
|
6
|
+
description: Use the fetch-data guide when sign-in or signout happens through RPC, then use the state guide for transient auth-adjacent request state, validation to guard credentials, and routing or project structure to place auth files correctly.
|
|
7
7
|
links:
|
|
8
8
|
- /docs/fetch-data
|
|
9
9
|
- /docs/state
|
|
@@ -50,6 +50,7 @@ from casp.auth import (
|
|
|
50
50
|
|
|
51
51
|
- Define app-wide auth behavior in `build_auth_settings()` and apply it once at startup with `configure_auth(...)`.
|
|
52
52
|
- Use `auth.sign_in(...)` and `auth.sign_out(...)` instead of setting or clearing session keys directly.
|
|
53
|
+
- Prefer `pp.rpc(...)` plus `@rpc(require_auth=True)` for signout buttons or menus rendered in pages or components. Use a dedicated signout route only when you need a plain HTML form POST or a no-JavaScript fallback.
|
|
53
54
|
- Use `@require_auth`, `@require_role`, and `@guest_only` for page access rules.
|
|
54
55
|
- Use `@rpc(require_auth=True, allowed_roles=[...])` for browser-triggered actions that need protection.
|
|
55
56
|
- Use `StateManager` only for transient auth-adjacent request state; keep the authenticated session itself owned by `casp.auth`.
|
|
@@ -112,12 +113,52 @@ Important behavior from the current implementation:
|
|
|
112
113
|
- `default_token_validity` is parsed by the installed auth runtime with the format `^\d+(s|m|h|d)$`. Use values such as `30m`, `1h`, or `7d`.
|
|
113
114
|
- `token_auto_refresh` only changes behavior when the request lifecycle calls `auth.refresh_session()`. In the installed `auth.py`, the flag alone does not refresh expiry by itself.
|
|
114
115
|
- The framework `AuthSettings` dataclass defaults `is_all_routes_private=True`, but the project example above explicitly changes that to `False`.
|
|
116
|
+
- In generated app-owned config like this workspace, `src/lib/auth/auth_config.py` starts with `is_all_routes_private=False`, so routes are public by default until the app chooses stricter route protection.
|
|
115
117
|
- `public_routes`, `auth_routes`, `private_routes`, and `role_based_routes` are exact path matches in the installed `Auth` methods.
|
|
116
118
|
- `private_routes` matters only when `is_all_routes_private=False`.
|
|
117
119
|
- `role_based_routes` currently expects `PATH -> [ROLES]`, not role names keyed to paths the other way around.
|
|
118
120
|
- `role_identifier` defaults to `role`, and the current `auth.sign_in(...)` flow also normalizes `userRole` into `role` when possible.
|
|
119
121
|
- `api_auth_prefix` defaults to `/api/auth` and should stay centralized here rather than being hard-coded across routes.
|
|
120
122
|
|
|
123
|
+
## Choosing Public vs Private Route Mode
|
|
124
|
+
|
|
125
|
+
Make this decision at app setup time in `src/lib/auth/auth_config.py`.
|
|
126
|
+
|
|
127
|
+
- In the default app-owned starter pattern used in this workspace, routes start public because `is_all_routes_private=False` in `src/lib/auth/auth_config.py`.
|
|
128
|
+
- If the application has only a few public pages and most routes require auth, set `is_all_routes_private=True` and list the exceptions in `public_routes`.
|
|
129
|
+
- If the application has many public pages and only a few protected areas, keep `is_all_routes_private=False` and list only the protected routes in `private_routes`.
|
|
130
|
+
- In the current runtime, `auth_routes=["/signin", "/signup"]` stays public by default, and most apps do not need to change it unless the user explicitly asks for different auth routes.
|
|
131
|
+
- In all-private mode, the default `public_routes=["/"]` keeps the home page public unless you change that list.
|
|
132
|
+
- `token_auto_refresh=True` does not make routes private. It only enables sliding-session refresh when the request lifecycle calls `auth.refresh_session()`.
|
|
133
|
+
- You do not need to modify Caspian core files for this decision. Keep the policy in `src/lib/auth/auth_config.py`.
|
|
134
|
+
- If you customize `src/lib/auth/auth_config.py`, add it to `excludeFiles` in `caspian.config.json` so update commands do not overwrite your local auth policy.
|
|
135
|
+
|
|
136
|
+
Example all-private setup with a few public exceptions:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
return AuthSettings(
|
|
140
|
+
default_token_validity="1h",
|
|
141
|
+
token_auto_refresh=False,
|
|
142
|
+
is_all_routes_private=True,
|
|
143
|
+
public_routes=["/", "/pricing", "/about"],
|
|
144
|
+
auth_routes=["/signin", "/signup"],
|
|
145
|
+
private_routes=[],
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Example mixed app with many public routes and only a few protected areas:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
return AuthSettings(
|
|
153
|
+
default_token_validity="1h",
|
|
154
|
+
token_auto_refresh=False,
|
|
155
|
+
is_all_routes_private=False,
|
|
156
|
+
public_routes=["/"],
|
|
157
|
+
auth_routes=["/signin", "/signup"],
|
|
158
|
+
private_routes=["/dashboard", "/settings", "/billing"],
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
121
162
|
## Environment Variables
|
|
122
163
|
|
|
123
164
|
The installed auth code reads several values from `.env` when explicit values are not passed.
|
|
@@ -414,16 +455,58 @@ src/
|
|
|
414
455
|
signup/
|
|
415
456
|
index.py
|
|
416
457
|
index.html
|
|
417
|
-
|
|
418
|
-
|
|
458
|
+
signout/
|
|
459
|
+
index.py
|
|
419
460
|
dashboard/
|
|
420
461
|
index.py
|
|
421
462
|
index.html
|
|
422
463
|
```
|
|
423
464
|
|
|
424
|
-
Use `guest_only()` on signin and signup routes, use `auth.sign_in(...)` inside the owning RPC action after validation and credential checks, and protect private destinations with `require_auth()` or central route policy.
|
|
465
|
+
Use `guest_only()` on signin and signup routes, use `auth.sign_in(...)` inside the owning RPC action after validation and credential checks, prefer RPC for signout UI actions, and protect private destinations with `require_auth()` or central route policy.
|
|
466
|
+
|
|
467
|
+
Preferred signout pattern: auth-protected RPC from a page or component.
|
|
468
|
+
|
|
469
|
+
Use this when the logout trigger lives in a page, layout, header, dropdown, or reusable component. The HTML can live at page level or component level.
|
|
470
|
+
|
|
471
|
+
```html
|
|
472
|
+
<div>
|
|
473
|
+
<button onclick="signout()">
|
|
474
|
+
Sign out
|
|
475
|
+
</button>
|
|
476
|
+
|
|
477
|
+
<script>
|
|
478
|
+
async function signout() {
|
|
479
|
+
await pp.rpc("signout");
|
|
480
|
+
}
|
|
481
|
+
</script>
|
|
482
|
+
</div>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
```python
|
|
486
|
+
from casp.auth import auth
|
|
487
|
+
from casp.rpc import rpc
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
@rpc(require_auth=True)
|
|
491
|
+
def signout():
|
|
492
|
+
return auth.sign_out()
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
Fallback signout pattern: dedicated route.
|
|
496
|
+
|
|
497
|
+
Use this when you need a plain HTML form POST, a no-JavaScript fallback, or a full-route signout endpoint.
|
|
498
|
+
|
|
499
|
+
HTML:
|
|
500
|
+
|
|
501
|
+
```html
|
|
502
|
+
<form action="/signout" method="post">
|
|
503
|
+
<button type="submit">
|
|
504
|
+
<span>Log Out</span>
|
|
505
|
+
</button>
|
|
506
|
+
</form>
|
|
507
|
+
```
|
|
425
508
|
|
|
426
|
-
|
|
509
|
+
Route: `src/app/(auth)/signout/index.py`
|
|
427
510
|
|
|
428
511
|
```python
|
|
429
512
|
from casp.auth import auth, require_auth
|
|
@@ -659,11 +742,17 @@ Validate and authenticate close to the input boundary.
|
|
|
659
742
|
Common placement patterns are:
|
|
660
743
|
|
|
661
744
|
- put centralized policy in `src/lib/auth/auth_config.py`
|
|
745
|
+
- decide public-vs-private route mode at app start in `src/lib/auth/auth_config.py` instead of scattering route privacy logic across route files
|
|
746
|
+
- use `is_all_routes_private=True` only when most routes should require auth; otherwise keep `is_all_routes_private=False` and maintain `private_routes`
|
|
747
|
+
- keep public exceptions in `public_routes`, and leave `auth_routes=["/signin", "/signup"]` alone unless the app explicitly needs different auth endpoints
|
|
662
748
|
- call `configure_auth(build_auth_settings())` during startup
|
|
663
|
-
- keep sign-in, signup,
|
|
749
|
+
- keep sign-in, signup, and reset-password handlers in the owning route backend under `src/app/**/index.py`
|
|
750
|
+
- prefer signout through `pp.rpc("signout")` with `@rpc(require_auth=True)` when the trigger lives in page or component UI
|
|
751
|
+
- use a dedicated signout route only for no-JavaScript, form-post, or full-navigation edge cases
|
|
664
752
|
- use `@rpc()` for browser-triggered auth actions and page decorators for full-route protection
|
|
665
753
|
- use `Validate` and `Rule` from `casp.validate` before password checks, user lookup, persistence, or external provider flows
|
|
666
754
|
- keep reusable auth helpers in `src/lib/auth/`
|
|
755
|
+
- protect customized auth policy files from updater overwrite with `excludeFiles` in `caspian.config.json`
|
|
667
756
|
|
|
668
757
|
For browser-triggered auth forms, pair this page with `fetch-data.md`. For credential and form validation, pair it with `validation.md`.
|
|
669
758
|
|
|
@@ -673,15 +762,22 @@ If an AI agent is deciding how to handle auth in Caspian, apply these rules firs
|
|
|
673
762
|
|
|
674
763
|
- Treat `casp.auth` as the default authentication layer.
|
|
675
764
|
- Centralize route visibility, redirects, and RBAC policy in `src/lib/auth/auth_config.py`.
|
|
765
|
+
- Decide route mode early in `src/lib/auth/auth_config.py`: use `is_all_routes_private=True` when most routes should require auth, otherwise keep `is_all_routes_private=False` and list protected routes in `private_routes`.
|
|
766
|
+
- In app-owned starter config like this workspace, treat `is_all_routes_private=False` as the default starting point, which means routes begin public until the app opts into stricter protection.
|
|
767
|
+
- Treat `public_routes` as the public exception list for all-private apps. In the current defaults, `/` stays public and `auth_routes=["/signin", "/signup"]` stays public too.
|
|
676
768
|
- Apply settings at startup in `main.py` with `configure_auth(build_auth_settings())`.
|
|
677
769
|
- Register provider instances in `main.py` with `Auth.set_providers(...)` when Google or GitHub OAuth is enabled.
|
|
678
770
|
- Use `auth.sign_in(...)` and `auth.sign_out(...)` for session lifecycle changes.
|
|
771
|
+
- Prefer `pp.rpc("signout")` plus `@rpc(require_auth=True)` for logout buttons or menus in pages and components.
|
|
772
|
+
- Use a dedicated `/signout` route only for plain HTML form POST, no-JavaScript fallback, or other full-navigation edge cases.
|
|
773
|
+
- Do not treat `token_auto_refresh` as a route-privacy switch. In the current app it only affects sliding-session refresh if `auth.refresh_session()` is called.
|
|
679
774
|
- Use `@require_auth`, `@require_role`, and `@guest_only` for page-level access rules.
|
|
680
775
|
- Use `@rpc(require_auth=True, allowed_roles=[...])` for protected browser-triggered actions.
|
|
681
776
|
- Keep `SessionMiddleware` outermost so auth, CSRF, and RPC handlers can read `request.session`.
|
|
682
777
|
- Use [state.md](./state.md) only for transient auth-adjacent request state, not as the auth session store.
|
|
683
778
|
- Align `SESSION_LIFETIME_HOURS` with `default_token_validity` unless you intentionally want different cookie and auth-payload expiry windows.
|
|
684
779
|
- Prefer exact route strings in `public_routes`, `auth_routes`, `private_routes`, and `role_based_routes`.
|
|
780
|
+
- Protect customized `src/lib/auth/auth_config.py` from updater overwrite by adding it to `excludeFiles` in `caspian.config.json`.
|
|
685
781
|
- Keep auth secrets and OAuth provider credentials in `.env`.
|
|
686
782
|
- Set `AUTH_COOKIE_NAME` explicitly so the session middleware cookie name and auth settings stay aligned.
|
|
687
783
|
- Use `.venv/Lib/site-packages/casp/auth.py` only when the task is about framework auth internals or debugging installed behavior.
|
package/dist/docs/commands.md
CHANGED
|
@@ -643,6 +643,10 @@ This is useful for protecting:
|
|
|
643
643
|
- entry-point files
|
|
644
644
|
- other locally modified framework-managed files
|
|
645
645
|
|
|
646
|
+
Auth example:
|
|
647
|
+
|
|
648
|
+
- add `./src/lib/auth/auth_config.py` to `excludeFiles` when you customize route privacy policy, public-route exceptions, redirects, or other app-specific auth settings there
|
|
649
|
+
|
|
646
650
|
If you exclude a file, the updater preserves it, but you are responsible for merging future framework changes into that file manually.
|
|
647
651
|
|
|
648
652
|
## 10. Operational Notes
|
package/dist/docs/index.md
CHANGED
|
@@ -40,7 +40,7 @@ The packaged Caspian docs distributed by the current toolchain also live here:
|
|
|
40
40
|
- `commands.md` - Main Caspian CLI workflows for project creation, generation, updates, and config-aware maintenance
|
|
41
41
|
- `mcp.md` - Workspace FastMCP server layout, nested config path, local launch flow, and MCP-specific AI routing rules
|
|
42
42
|
- `database.md` - Prisma schema, migration, seed, and client-generation workflow for the current workspace, plus Python-side helper caveats
|
|
43
|
-
- `auth.md` - Session-backed authentication with `casp.auth`, centralized `auth_config.py`,
|
|
43
|
+
- `auth.md` - Session-backed authentication with `casp.auth`, centralized `auth_config.py`, public-vs-private route mode guidance, RPC-first signout guidance, RBAC, and OAuth provider helpers
|
|
44
44
|
- `components.md` - Create reusable Python components, template-backed UI, JSX-style imports, and the single-parent root rule for component HTML files
|
|
45
45
|
- `pulsepoint.md` - Default reactive frontend runtime contract for component scripts, state, effects, directives, and client-side behaviors
|
|
46
46
|
- `fetch-data.md` - Initial server-side data loading and browser-triggered RPC flows with `pp.rpc()`, streaming, uploads, and auth-aware actions
|
|
@@ -88,7 +88,7 @@ Once the project is scaffolded:
|
|
|
88
88
|
|
|
89
89
|
- Read `database.md` when the app includes Prisma ORM support or needs database changes.
|
|
90
90
|
- Read `mcp.md` when the app includes MCP support or needs FastMCP server, config, or launch-flow changes.
|
|
91
|
-
- Read `auth.md` before wiring session config, sign-in or signout
|
|
91
|
+
- Read `auth.md` before choosing public-vs-private route mode, wiring session config, sign-in or signout flows, route guards, or OAuth providers.
|
|
92
92
|
- Read `pulsepoint.md` before generating interactive frontend behavior.
|
|
93
93
|
- Read `fetch-data.md` before adding browser-triggered reads, writes, uploads, or streams.
|
|
94
94
|
- Read `validation.md` before handling forms, auth input, or RPC payloads.
|