polish: drop dead CSS, fix docstring drift, add agent-prompt route test

This commit is contained in:
ZdenekSrotyr 2026-05-02 22:02:03 +02:00
parent ecb6c35ad5
commit 60386b9c3c
5 changed files with 15 additions and 98 deletions

View file

@ -13,7 +13,7 @@ CalVer image tags (`stable-YYYY.MM.N`, `dev-YYYY.MM.N`) are produced for every C
### Added ### Added
- **Agent Setup Prompt** — admins can customise the `CLAUDE.md` generated for analysts by `da analyst setup`. Default ships at `config/claude_md_template.txt` (Jinja2 syntax). Edit at `/admin/agent-prompt` or via REST: `GET /api/admin/welcome-template` returns `{content, default, updated_at, updated_by}`; `PUT` to set; `DELETE` to clear; `POST /api/admin/welcome-template/preview` for live preview without persisting. `GET /api/welcome` returns the prompt rendered for the calling user (RBAC-filtered `marketplaces`). See `docs/agent-setup-prompt.md` for the full placeholder reference. - **Agent Setup Prompt** — admins can customise the `CLAUDE.md` generated for analysts by `da analyst setup`. Default ships at `config/claude_md_template.txt` (Jinja2 syntax). Edit at `/admin/agent-prompt` or via REST: `GET /api/admin/welcome-template` returns `{content, default, updated_at, updated_by}`; `PUT` to set; `DELETE` to clear; `POST /api/admin/welcome-template/preview` for live preview without persisting. `GET /api/welcome` returns the prompt rendered for the calling user (RBAC-filtered `marketplaces`). See `docs/agent-setup-prompt.md` for the full placeholder reference.
- DuckDB schema v21: `welcome_template` singleton table for the per-instance override. Auto-migration v20→v21 on first start. - DuckDB schema v21: `welcome_template` singleton table for the per-instance override. Auto-migration on first start (current schema reaches v22 — see also the v22 reservation note below).
- DuckDB schema v22: reserved (`setup_banner` table retained for forward compatibility with already-migrated instances; feature dropped). - DuckDB schema v22: reserved (`setup_banner` table retained for forward compatibility with already-migrated instances; feature dropped).
- New `instance.sync_interval` setting in `instance.yaml` (default `"1 hour"`) — surfaced in the agent setup prompt as `{{ sync_interval }}`. - New `instance.sync_interval` setting in `instance.yaml` (default `"1 hour"`) — surfaced in the agent setup prompt as `{{ sync_interval }}`.

View file

@ -135,7 +135,7 @@ async def admin_preview_template(
conn: duckdb.DuckDBPyConnection = Depends(_get_db), conn: duckdb.DuckDBPyConnection = Depends(_get_db),
): ):
"""Render arbitrary template content against the live context for the """Render arbitrary template content against the live context for the
calling admin, without persisting. Used by the /admin/welcome editor's calling admin, without persisting. Used by the /admin/agent-prompt editor's
Preview button so admins can see their edits before saving.""" Preview button so admins can see their edits before saving."""
env = Environment(undefined=StrictUndefined, autoescape=False) env = Environment(undefined=StrictUndefined, autoescape=False)
try: try:

View file

@ -1270,66 +1270,6 @@
cursor: wait; cursor: wait;
} }
/* ── Setup instructions preview (read-only card inside env-setup-cta) ── */
.setup-preview-card {
margin-top: 18px;
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 8px;
padding: 14px 16px;
}
.setup-preview-summary {
list-style: none;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
user-select: none;
}
.setup-preview-summary::-webkit-details-marker { display: none; }
.setup-preview-chevron {
display: inline-block;
font-size: 11px;
color: rgba(255, 255, 255, 0.7);
transition: transform 0.15s ease;
}
details[open] > .setup-preview-summary .setup-preview-chevron { transform: rotate(90deg); }
.setup-preview-title {
font-size: 12px;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: uppercase;
color: rgba(255, 255, 255, 0.85);
margin: 0;
}
.setup-preview-sub {
font-size: 12px;
color: rgba(255, 255, 255, 0.65);
margin: 0 0 10px 0;
}
.setup-preview-pre {
background: #1e1e2e;
border-radius: 6px;
padding: 14px 16px;
margin: 0;
max-height: 400px;
overflow-y: auto;
font-family: var(--font-mono);
font-size: 12.5px;
line-height: 1.55;
color: #cdd6f4;
white-space: pre-wrap;
word-break: break-word;
}
.setup-preview-code { font-family: inherit; font-size: inherit; }
.setup-preview-pre .placeholder-token {
background: rgba(249, 226, 175, 0.12);
color: #f9e2af;
padding: 0 4px;
border-radius: 3px;
font-style: italic;
}
/* Fallback modal (when clipboard is blocked) */ /* Fallback modal (when clipboard is blocked) */
.setup-fallback-overlay { .setup-fallback-overlay {
position: fixed; position: fixed;
@ -1396,35 +1336,6 @@
border-color: var(--primary); border-color: var(--primary);
} }
/* ── Setup Banner (bottom, for returning users) ── */
.setup-banner {
background: var(--background);
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px 24px;
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
}
.setup-banner-text {
display: flex;
flex-direction: column;
gap: 2px;
}
.setup-banner-title {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
}
.setup-banner-desc {
font-size: 12px;
color: var(--text-secondary);
}
.btn-setup-secondary { .btn-setup-secondary {
font-family: var(--font-primary); font-family: var(--font-primary);
font-size: 13px; font-size: 13px;
@ -1978,13 +1889,6 @@
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
.setup-banner {
flex-direction: column;
gap: 20px;
text-align: center;
padding: 28px 24px;
}
.onboard-label { .onboard-label {
flex-wrap: wrap; flex-wrap: wrap;
} }

View file

@ -9,6 +9,7 @@ Two layers:
The Jinja2 environment uses StrictUndefined so that any typo in the The Jinja2 environment uses StrictUndefined so that any typo in the
template raises immediately rather than rendering empty strings. template raises immediately rather than rendering empty strings.
""" """
# See also: surfaced as the "Agent Setup Prompt" admin editor at /admin/agent-prompt.
from __future__ import annotations from __future__ import annotations

View file

@ -278,6 +278,18 @@ class TestAdminRoleGuards:
resp = web_client.get("/corporate-memory/admin", cookies=analyst_cookie) resp = web_client.get("/corporate-memory/admin", cookies=analyst_cookie)
assert resp.status_code == 403 assert resp.status_code == 403
def test_admin_agent_prompt_page_admin_only(self, web_client, admin_cookie, analyst_cookie):
"""The renamed Agent Setup Prompt page is gated by require_admin."""
# Unauthenticated → 302 redirect to login
r = web_client.get("/admin/agent-prompt", follow_redirects=False)
assert r.status_code in (302, 401, 403)
# Non-admin → 403
r = web_client.get("/admin/agent-prompt", cookies=analyst_cookie, follow_redirects=False)
assert r.status_code == 403
# Admin → 200
r = web_client.get("/admin/agent-prompt", cookies=admin_cookie, follow_redirects=False)
assert r.status_code == 200
class TestUnauthenticatedHtmlRedirects: class TestUnauthenticatedHtmlRedirects:
def test_dashboard_unauthenticated_redirects_to_login(self, web_client): def test_dashboard_unauthenticated_redirects_to_login(self, web_client):