Skip to content

UI-SP3 — Infrastructure & Governance (Executors / Audit / Quota / Settings)#21

Merged
l17728 merged 19 commits into
mainfrom
feat/ui-sp3-infra-governance
May 20, 2026
Merged

UI-SP3 — Infrastructure & Governance (Executors / Audit / Quota / Settings)#21
l17728 merged 19 commits into
mainfrom
feat/ui-sp3-infra-governance

Conversation

@l17728
Copy link
Copy Markdown
Owner

@l17728 l17728 commented May 20, 2026

Summary

Web UI sub-project 3 of 5 (after UI-SP1 = PR #19 and UI-SP2 = PR #20 de9573a). Full-stack but additive, zero Alembic migration (all columns already existed; only policy.csv and openapi.yaml extended additively).

  • Backend (2 additive read-only endpoints + 6 casbin grants):
    • GET /api/v1/audit/log — tenant-scoped audit search (filters: action prefix, actor_user_id, from/to time range; cursor-paginated). Implements the already-declared searchAuditLog contract (with an additive next_cursor synced into openapi.yaml).
    • GET /api/v1/executors — browser-facing executor list (own-tenant + shared-infra; system_admin / is_service sees all). Lives in a new module src/dlw/api/executors_read.py because the existing api/executors.py is mTLS-only per tools/lint_invariants.py:check_no_bearer_on_executor_routes. openapi.yaml extends ExecutorRead additively (4 required fields preserved + 7 nullable additions) and adds ExecutorListResponse.
    • policy.csv: 6 new tenant_match GET grants for /api/v1/audit* and /api/v1/executors* across tenant_admin/operator/viewer.
  • Frontend (4 new pages, 4 components, 3 composables): /executors (host-grouped list + status filter), /audit (filterable + cursor pagination), /quota (3 cards over the existing /quota/current), /settings (frontend-only: principal info from stores/session.ts, theme/locale toggles, /health/active widget). All polling flows through the single useLiveResource seam (with the SP2-added enabled option). No new runtime dep.
  • TDD cycle: 16 bite-sized tasks across M1–M4; 2 opus pre-execution reviewers (fixed 2 BLOCKERs in the plan before code: missing policy.csv grants; main.py router-include idiom mismatch); final opus review caught 1 HIGH (Audit "Load older" cursor not advancing → duplicates on 2nd click) and 1 MEDIUM (actor_user_id undefined guard) — both fixed pre-merge with a new regression test.

Verification

  • Backend: 447 pytest pass (439 prior + 8 new). spectral + swagger-cli + lint_invariants + lint_no_direct_status_write all green.
  • Frontend: 126 vitest pass, vue-tsc strict 0 errors, eslint --max-warnings=0, vite build ok; en/zh locale parity test green.
  • Live headed-Playwright smoke against a freshly-started :8011 controller (current SP3 code): 3 endpoints (audit/log, executors, quota/current) returned 200 with real data; all 4 pages rendered correctly with zh-CN locale, real local-host-worker-1 healthy executor, host grouping, Settings showed principal (user=1, tenant=1, role=tenant_admin), theme switch + locale radio + system section.

Known follow-ups (non-blocking)

  • Audit el-date-picker value-format="YYYY-MM-DDTHH:mm:ss[Z]" produces a literal Z on a locally-rendered time → off-by-tz filter; acceptable for v1, proper tz-aware picker tracked.
  • Deferred (no backend support today): executor drain/restart, metrics history, heartbeat history; HF-token rotation; license-policy CRUD; source-driver registration; maintenance mode; /quota/usage; ML forecast; chargeback PDF; real-time audit tail (UI-SP5).

Test plan

  • CI green (OpenAPI, Invariant, pytest, frontend-lint, frontend-build, + others)
  • Squash-merge with --delete-branch

🤖 Generated with Claude Code

l17728 and others added 19 commits May 20, 2026 07:12
…/ Settings)

Additive: 2 read endpoints (searchAuditLog already declared; new listExecutors
in new file to satisfy lint_no_bearer_on_executor_routes) + 4 frontend pages
(Settings is frontend-only). Zero migration; all 'designed-only' features
(drain/restart, executor metrics history, HF-token rotate, license CRUD,
quota usage history, real-time tail, ML forecast, chargeback PDF) explicitly
deferred & documented. Inherits all UI-SP1/SP2 locked decisions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
M1 backend (1 openapi extend+add, 2 endpoints w/ tests, gate), M2 frontend
foundation (types, format utils, 3 composables, gate), M3 components (4
visual), M4 i18n parity + 4 pages + router/nav + full gate + headed smoke +
docs. Complete code, no placeholders; grounded in verified on-disk
contract + lint-rule placement constraints.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…review

- Backend B1: policy.csv grants for /api/v1/audit* + /api/v1/executors*
  (tenant_admin/operator/viewer GET) — without these all auth'd tests 403
- Backend B2: src/dlw/main.py router-include is inside create_app() with
  `from dlw.api.X import router as X_router` — plan now spells exact patches
- Contract sync: also extend openapi.yaml searchAuditLog response with the
  additive `next_cursor` field so static contract matches runtime DTO
- Frontend BL-1: QuotaCard.spec.ts ran before i18n add → en.quotaPage was
  undefined → TypeError; inline expected key-path strings
- Frontend IM-1: widen el-radio-group @update:model-value param to the full
  emit union to satisfy vue-tsc strict
- Frontend IM-3: add :step=1 :precision=0 to el-input-number actor filter

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ponse+searchAuditLog next_cursor) + policy.csv grants for audit/executors
- HIGH: Audit "Load older" reused page-1's next_cursor → duplicate rows
  on the second click. Added an `olderCursor` ref watched off the live
  query's next_cursor (immediate=true) and advanced after each
  fetchOlderAudit; button gated by it; reset() clears it. Added a 3-row
  regression test that clicks twice and asserts cursor advances + button
  disappears at exhaustion.
- MEDIUM: useAuditLog.buildQuery actor guard hardened from `!== null` to
  `typeof === 'number' && Number.isFinite(...)` so a stray undefined from
  el-input-number's clear path can't become `actor_user_id=undefined`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@l17728 l17728 merged commit a32f165 into main May 20, 2026
12 checks passed
@l17728 l17728 deleted the feat/ui-sp3-infra-governance branch May 20, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant