Polish pass after the big refactor in 2d114fc.
== Header elevation slot propagated ==
shared/elevation.{js,css} surface a header checkbox for admins.
30-minute sudo-style cookie window (Max-Age=1800, SameSite=Lax).
Only renders when /.profile/access reports can_elevate=true; quiet
for non-admins. Slot added to all 7 tool templates and concat'd
into all 7 build.sh files; admin in any tool now sees the toggle.
Three text-rename ride-alongs in archive/classifier/transmittal
templates: "Add Local Directory" → "Use Local Directory" (the same
rename that landed in browse earlier in this branch).
== Docs ==
- CLAUDE.md gets an "Admin elevation is sudo-style" paragraph in
the "Things that bite if you forget" section.
- AGENTS.md gets a dedicated "Admin elevation (sudo-style)" section
alongside "Bearer tokens" — same depth as the existing auth docs.
== Helper file splits ==
The retired form editor's shared helpers got bundled into a single
zddc_admin.go in the cleanup; that name is now misleading. Split by
concern:
- admin_helpers.go: hasAnyAdminScope (the only admin-specific helper)
- paths.go: resolvePath, urlPathOf, chainDirs (URL ↔ filesystem path
math — used by several profile / zddc-file handlers)
- profile_assets.go (renamed from zddc_admin_assets.go): custom CSS
pipeline. URL renamed from /.profile/zddc/assets/ → /.profile/assets/
since /.profile/zddc/ no longer hosts an editor.
- treeEntry moves to profilehandler.go (alongside AccessView, its
only consumer).
- writeError moves to profileprojects.go (its only consumer).
== Smell cleanup ==
- zddc.HasAnyAdminGrant(fsRoot, email) — new elevation-independent
primitive that walks the cascade and reports whether email is named
in any admin: list anywhere. Replaces the synthetic-elevated probe
hack in enumerateAccess (`Principal{Email, Elevated: true}` was
"lying" to the elevation gate to ask what it would say). The handler's
hasAnyAdminScope collapses to a 4-line wrapper that gates on
p.Elevated and delegates.
- Access-log middleware records `elevated` per request, so forensics
can distinguish "admin acting as user" from "admin exercising power."
- browse/js/app.js's ?file= deep link walks multi-segment paths. Each
intermediate segment is matched + expanded; the leaf gets
selected/previewed. Auto-shows hidden when any segment starts with
. or _. Silently no-ops on unresolved segments.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
47 lines
1.3 KiB
CSS
47 lines
1.3 KiB
CSS
/* shared/elevation.css — admin-elevation toggle in the tool header.
|
|
Renders only for users with admin scope (handled by elevation.js;
|
|
the placeholder is `.hidden` by default). When visible, sits left
|
|
of the theme button — sudo-style affordance for opting into admin
|
|
powers. */
|
|
|
|
.elevation-toggle {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.3rem;
|
|
font-size: 0.78rem;
|
|
color: var(--text-muted);
|
|
user-select: none;
|
|
cursor: pointer;
|
|
padding: 0.15rem 0.45rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--bg);
|
|
transition: background 0.12s, border-color 0.12s, color 0.12s;
|
|
}
|
|
|
|
.elevation-toggle:hover {
|
|
background: var(--bg-hover);
|
|
border-color: var(--border-dark);
|
|
}
|
|
|
|
.elevation-toggle input[type="checkbox"] {
|
|
margin: 0;
|
|
cursor: pointer;
|
|
accent-color: var(--danger);
|
|
}
|
|
|
|
.elevation-toggle__label {
|
|
cursor: pointer;
|
|
letter-spacing: 0.02em;
|
|
}
|
|
|
|
/* Active state — when elevation is ON, the toggle reads as "armed"
|
|
so the user can't miss that admin powers are currently live.
|
|
:has(:checked) lets us style the wrapper based on the inner
|
|
checkbox without JS. */
|
|
.elevation-toggle:has(input:checked) {
|
|
background: rgba(220, 53, 69, 0.12);
|
|
border-color: var(--danger);
|
|
color: var(--danger);
|
|
font-weight: 600;
|
|
}
|