1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
[]
= "umbral-admin"
= "Auto-generated CRUD admin UI for umbral models."
# Plugins live under `plugins/` (a sibling of `crates/`), so the
# workspace pointer matches what umbral-auth does.
= "../.."
= true
= true
= true
= true
= true
= true
[]
= { = "../../crates/umbral", = "0.0.12" }
# axum is needed for State + Query extractors used by the new AdminConfig
# routing surface. umbral's web re-exports don't include State.
= "0.8"
# Required for the auth gate. The admin uses umbral-auth's
# `authenticate` helper to verify credentials on login.
= { = "../umbral-auth", = "0.0.12" }
# Feature #75: per-model permission checks. The admin calls
# `umbral_permissions::has_perm_for_superuser` at the top of every
# CRUD handler. When PermissionsPlugin is NOT installed, all checks
# short-circuit to allow (preserves pre-#75 staff-only gating).
= { = "../umbral-permissions", = "0.0.12" }
# Session management: create_session, login, logout, current_user.
# Used by the HTML login flow to replace the old Basic Auth challenge.
= { = "../umbral-sessions", = "0.0.12" }
# CSRF token generation for the login form. The admin embeds a
# hidden csrf_token field and verifies it on POST /admin/login.
# We reuse umbral-security's generate_token() rather than rolling our own.
= { = "../umbral-security", = "0.0.12" }
# Form decoding + row marshalling. The admin parses POST bodies
# through `serde_urlencoded` (axum's `Form` extractor under the
# hood) and writes them back through dynamic sqlx::query calls.
= { = "1", = ["derive"] }
= "1"
= "0.7"
= { = "0.4", = ["serde"] }
= { = "0.8", = ["sqlite", "runtime-tokio", "chrono", "uuid"] }
= { = "1", = ["serde", "v7"] }
# Admin owns its own minijinja Environment with the embedded
# templates from `templates/`. The framework's ambient template
# engine is OnceLock-protected so the admin can't register into it
# after `App::build` runs; a private env is cleaner anyway since the
# admin's templates are an internal API.
= "2"
# Server-side logging of admin database errors. The error response
# returns a fixed string to the browser; the full sqlx error goes
# here so operators can debug without leaking query fragments to
# (potentially compromised) staff sessions.
= "0.1"
# Phase 4: on_ready spawns async table creation via tokio::runtime::Handle.
= { = "1", = ["rt"] }
# Concurrent COUNT futures for the dashboard's per-model row counters
# (was a real N+1 from the user's perspective: every additional model
# registered added another sequential round-trip to /admin/).
= "0.3"
[]
= { = "1", = ["macros", "rt", "rt-multi-thread", "sync"] }
= "3"
= { = "0.5", = ["util"] }
= "1"
= "0.1"
= "0.8"
= "0.7"
= { = "1", = ["derive"] }
= "1"
= { = "0.4", = ["serde"] }
= { = "0.8", = ["sqlite", "runtime-tokio", "chrono", "uuid"] }
= { = "../umbral-auth" }
= { = "../umbral-sessions" }