功能修改
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-07-18
|
||||
@@ -0,0 +1,92 @@
|
||||
## Context
|
||||
|
||||
The console already has five required first-party areas, typed Platform API clients, role-scoped routes, long-running job polling, operation tracking, and the black-mecha/magical-girl theme system. The remaining problem is cohesion and truthfulness: the overview hides some API failures as empty collections, page mutations use inconsistent busy/confirm/retry behavior, and operators lack a compact cross-page view of active and failed work.
|
||||
|
||||
This change stays inside `platform_web/` and consumes existing Platform API projections. It does not make the browser a source of truth for jobs, resource state, permissions, or secrets.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Make loading, empty, unavailable, stale, active, succeeded, and failed states visually and semantically distinct.
|
||||
- Give operators an actionable overview of server health, Run endpoint safe status, active/failed jobs, AI provider availability, resource pressure, and recent audit signals.
|
||||
- Standardize mutation behavior around permission gating, confirmation where state is disruptive, action-level busy state, persisted response handling, and retry after failure.
|
||||
- Keep first-party list pages full-width and dense while retaining modal/detail-route workflows.
|
||||
- Preserve the theme and responsive contracts at desktop and 390px.
|
||||
- Recover narrow-screen vertical space by moving the existing ordered text navigation into an off-canvas sidebar with a small theme-aware left-edge handle and bounded swipe gesture.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- No new Platform or Run endpoint, persistence model, permission, or job state machine.
|
||||
- No raw secret/key/token/path/PID/socket/credential/DSN/RCON projection.
|
||||
- No billing, cloud hosting sales, provider marketplace, fleet orchestration, arbitrary shell, or direct browser-to-Run channel.
|
||||
- No route, sidebar order, theme palette, or global particle architecture replacement.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Aggregate existing safe APIs in the browser without inventing platform health
|
||||
|
||||
The overview will fetch server instances, safe Run endpoint projections, jobs, metrics, platform usage, AI providers, and audit events as independent modules. Each module keeps its own state and refresh timestamp. Failed modules remain visibly unavailable and are excluded from healthy/empty conclusions.
|
||||
|
||||
Alternative considered: add one new dashboard API. Rejected because current APIs already provide the bounded projections needed, and this change does not need a new backend contract.
|
||||
|
||||
### Decision 2: Derive operational summaries in shared pure contracts
|
||||
|
||||
Job buckets, attention signals, server list sorting/filtering, provider summaries, and safe operation labels will live outside page components. Pages render derived view contracts and tests can lock classification without constructing full page trees.
|
||||
|
||||
Alternative considered: calculate every summary inline. Rejected because the same terminal/active/failure classification is needed by the overview, server page, and global operation tray.
|
||||
|
||||
### Decision 3: Platform responses remain authoritative
|
||||
|
||||
Mutations only update resource state from a successful Platform response or a subsequent refresh. Long-running operations use real job IDs and job polling. A rejected request keeps the previous resource state, preserves the failure message, and exposes retry where the same request remains valid.
|
||||
|
||||
Alternative considered: optimistic state transitions. Rejected because plugin/provider/server operations can be rejected by ownership, lifecycle, dependency, or reference constraints.
|
||||
|
||||
### Decision 4: Disruptive state changes use a shared confirmation contract
|
||||
|
||||
Plugin install/enable/disable, AI provider enable/disable/retire, user deactivation, and server destructive actions require resource-specific confirmation. Dialogs close on Escape or cancellation, preserve focus behavior, and disable duplicate submission while busy.
|
||||
|
||||
Alternative considered: confirm only destructive deletes. Rejected because enable/disable and install actions can interrupt running capabilities or create durable work.
|
||||
|
||||
### Decision 5: Capabilities control commands, routes control discovery
|
||||
|
||||
The existing route capability mapping remains the navigation authority. Within an allowed page, mutation controls check the matching session capability and render a clear read-only state when missing. The browser does not elevate access and still handles Platform 401/403 as authoritative rejection.
|
||||
|
||||
Alternative considered: hide every unauthorized control. Rejected because operators benefit from understanding why a page is read-only; safety-critical commands remain unavailable.
|
||||
|
||||
### Decision 6: Extend the existing theme system with shared operational primitives
|
||||
|
||||
New pulse rows, module status headers, compact job rows, and the operation tray use shared classes appended to `theme/base.css`, `var(...)` tokens, existing radius limits, and theme-specific material variables. Global decoration remains exclusively in `MagicalParticleLayer`.
|
||||
|
||||
Alternative considered: page-local cards and effects. Rejected because they would fragment theme switching and violate the repository style contract.
|
||||
|
||||
### Decision 7: Use an off-canvas text sidebar on narrow screens
|
||||
|
||||
At 760px and below, the sidebar leaves normal document flow and stays closed until the operator activates the left-edge handle or completes a rightward swipe that begins at the viewport edge. The drawer preserves the desktop route order, icons, Chinese labels, account access, and session operations; backdrop click, Escape, route selection, and a leftward drawer swipe close it.
|
||||
|
||||
Alternative considered: keep the horizontal icon rail and account strip above every page. Rejected because it consumes scarce vertical space, hides route labels, and makes repeated mobile operations slower to scan.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Independent overview requests can complete out of order. Mitigation: refresh callbacks update only their module and use explicit loading/ready/error states.
|
||||
- [Risk] More status rows can overload narrow layouts. Mitigation: collapse multi-column regions to a single ordered flow at 390px and keep command rows bounded.
|
||||
- [Risk] Horizontal content gestures can open navigation accidentally. Mitigation: require the opening swipe to start within the left 28px edge and travel at least 56px, while drawer-closing swipes use the inverse threshold.
|
||||
- [Risk] In-session operation history is not durable. Mitigation: label it as current-session request feedback; durable job and audit history continues to come from Platform APIs.
|
||||
- [Risk] Existing item 8 edits overlap `base.css` and API types. Mitigation: reuse its current worktree state, append narrowly scoped classes, and avoid reverting or rewriting lifecycle code.
|
||||
- [Risk] Action confirmation can add friction. Mitigation: require it only for persistent or disruptive operations; refresh and navigation remain immediate.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add shared derived contracts and tests.
|
||||
2. Add shared operation tray and accessible dialog behavior.
|
||||
3. Update each first-party page while keeping existing API methods and routes.
|
||||
4. Add shared theme styles and responsive rules.
|
||||
5. Run frontend tests/typecheck/build, structure validation, strict OpenSpec validation, and browser acceptance in both themes and at 390px.
|
||||
|
||||
Rollback is frontend-only: remove the new shared components/contracts and restore the previous page render paths. No persisted data migration is required.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Resolved: this change uses existing APIs and does not add a dashboard endpoint.
|
||||
- Resolved: the operation tray is session-scoped feedback; Platform jobs and audit events remain durable truth.
|
||||
- Resolved: development fixtures may remain in tests, but normal page rendering does not silently substitute them for failed APIs.
|
||||
@@ -0,0 +1,31 @@
|
||||
## Why
|
||||
|
||||
The first-party console has real management APIs and complete resource workflows, but operators still have to infer platform health across pages, some API failures are rendered as empty success states, and several state-changing actions lack a consistent confirm, progress, and recovery cycle. The next console iteration must turn the existing pages into a cohesive operations workspace without weakening permission or secret boundaries.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a permission-aware operations overview that distinguishes live, delayed, failed, empty, and unavailable API modules and surfaces active or failed jobs, endpoint health, resource pressure, and actionable navigation.
|
||||
- Deepen server management with explicit telemetry availability, job-state summaries, deterministic refresh behavior, and recovery-oriented feedback while retaining real job polling for long-running work.
|
||||
- Deepen plugin marketplace operations with permission gating, confirmation for state changes, persisted-response refresh, action progress, and retryable failures.
|
||||
- Remove normal-page user fixture fallbacks and add API-backed search, role/status filtering, operational summaries, retry, and mutation feedback.
|
||||
- Deepen AI provider management with retryable loading, action-level busy states, confirmation for enable/disable/retire operations, saved-response refresh, and safe configuration presence rather than raw key disclosure.
|
||||
- Add a compact global operation tray for in-session API mutations, including pending, succeeded, and failed records with diagnostic context and page-safe target labels.
|
||||
- Replace the narrow-screen top navigation stack with a theme-aware off-canvas sidebar that keeps Chinese labels visible, opens from a bounded left-edge control or rightward edge swipe, and closes without consuming page height.
|
||||
- Preserve the existing black-mecha and magical-girl crystal-moonlight theme system, shared surfaces, route order, and `MagicalParticleLayer` ownership.
|
||||
- Keep browser and plugin projections free of raw keys, tokens, secret values, host paths, PIDs, sockets, credentials, DSNs, RCON data, and direct Run endpoints.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `platform-operations-console-enrichment`: Permission-aware, API-backed operations views and mutation recovery workflows across overview, servers, plugins, users, and AI providers.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
None.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affects `platform_web/` contracts, shared components, operation tracking, first-party pages, theme styles, tests, and browser acceptance coverage.
|
||||
- Uses existing Platform APIs for server instances, Run endpoint safe projections, jobs, metrics, audit events, plugins, users, and AI providers; no new direct Run or secret-bearing browser contract is introduced.
|
||||
- Does not add billing, cloud host sales, provider marketplaces, arbitrary remote execution, or unrelated SaaS features.
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Permission-aware operations overview
|
||||
The console SHALL provide an overview that derives server, Run endpoint, job, resource, AI provider, and audit summaries from Platform API responses permitted for the active session.
|
||||
|
||||
#### Scenario: Operator opens overview with available APIs
|
||||
- **WHEN** the active session can read the overview and the required Platform APIs return data
|
||||
- **THEN** the console shows real counts, resource measurements, active and failed job summaries, endpoint health, and actionable signals derived from those responses
|
||||
|
||||
#### Scenario: Session lacks a management capability
|
||||
- **WHEN** a session can view an operational resource but lacks the capability required to mutate it
|
||||
- **THEN** the console presents a read-only explanation and does not dispatch the mutation
|
||||
|
||||
### Requirement: Independent module truth and recovery
|
||||
Each overview and management data module MUST distinguish loading, ready-empty, ready-data, and unavailable states, and MUST provide scoped retry without treating an API failure as an empty or healthy result.
|
||||
|
||||
#### Scenario: Audit API fails while core overview succeeds
|
||||
- **WHEN** server and job APIs succeed but the audit API fails
|
||||
- **THEN** core health remains visible, audit signals are marked unavailable, and the page does not claim that there are no recent audit signals
|
||||
|
||||
#### Scenario: Failed module is retried
|
||||
- **WHEN** an operator retries an unavailable module and its API succeeds
|
||||
- **THEN** only that module transitions to ready data and its refresh timestamp is updated
|
||||
|
||||
### Requirement: Real job and mutation progress
|
||||
Long-running work MUST use Platform job identifiers and job states, while immediate mutations MUST remain pending until the Platform response returns and MUST never use timers or optimistic local success.
|
||||
|
||||
#### Scenario: Long-running server operation is queued
|
||||
- **WHEN** a server operation returns a job identifier
|
||||
- **THEN** the console polls the Platform job projection and shows queued, claimed, running, retrying, terminal success, or terminal failure from that projection
|
||||
|
||||
#### Scenario: Mutation is rejected
|
||||
- **WHEN** the Platform rejects a plugin, user, server, or AI provider mutation
|
||||
- **THEN** the previous resource state remains visible and the console shows the rejection with a retry or corrective action when applicable
|
||||
|
||||
### Requirement: Confirmed disruptive operations
|
||||
Persistent or disruptive resource state changes MUST require resource-specific confirmation and MUST prevent duplicate submission while a request is pending.
|
||||
|
||||
#### Scenario: Plugin state change is confirmed
|
||||
- **WHEN** an authorized operator chooses install, enable, or disable and confirms the named plugin action
|
||||
- **THEN** the console dispatches one Platform request, disables duplicate confirmation, and refreshes state from the persisted response
|
||||
|
||||
#### Scenario: Confirmation is cancelled
|
||||
- **WHEN** an operator cancels a confirmation or presses Escape before submission
|
||||
- **THEN** no mutation is dispatched and the current resource state is preserved
|
||||
|
||||
### Requirement: Server operations workspace
|
||||
Server management SHALL expose API telemetry availability, deterministic search/filter/sort, active and failed job counts, and recovery-oriented navigation without covering or reflowing server-card operational data.
|
||||
|
||||
#### Scenario: Metrics are unavailable
|
||||
- **WHEN** the server list succeeds but metrics loading fails
|
||||
- **THEN** server cards remain available, metrics are labeled unavailable rather than zero, and a scoped metrics retry is offered
|
||||
|
||||
#### Scenario: Server has active or failed jobs
|
||||
- **WHEN** Platform jobs reference a visible server
|
||||
- **THEN** the server working surface shows the real active or failed job count and lets the operator open the server detail or job progress workflow
|
||||
|
||||
### Requirement: Plugin marketplace operations
|
||||
The plugin marketplace SHALL use Platform list/detail/state responses, permission-gated commands, confirmation, action progress, and failure recovery without production fallback data.
|
||||
|
||||
#### Scenario: Plugin state response succeeds
|
||||
- **WHEN** the Platform accepts a confirmed plugin state action
|
||||
- **THEN** list and detail views update from the returned or refreshed Platform plugin state and the action result is traceable
|
||||
|
||||
#### Scenario: Plugin detail refresh fails
|
||||
- **WHEN** the selected plugin summary exists but its detail API fails
|
||||
- **THEN** the summary remains visible, detail is marked unavailable, and the operator can retry detail loading without reloading the page
|
||||
|
||||
### Requirement: User management operations
|
||||
User management SHALL render only Platform API data in normal operation and SHALL provide search, role/status filtering, create/edit/status/deactivate feedback, and API-scoped retry.
|
||||
|
||||
#### Scenario: User API fails in development
|
||||
- **WHEN** the normal user list API fails in a development build
|
||||
- **THEN** the page shows an unavailable state and does not replace the result with actionable sample users
|
||||
|
||||
#### Scenario: User filters are applied
|
||||
- **WHEN** an authorized operator enters a query or selects role/status filters
|
||||
- **THEN** the full-width user working surface shows only matching Platform users and keeps create/edit flows in dialogs
|
||||
|
||||
### Requirement: AI provider operations
|
||||
AI provider management SHALL provide scoped list retry, action-level busy states, confirmed status/retirement changes, persisted-response refresh, and safe key configuration presence.
|
||||
|
||||
#### Scenario: Provider load is retried
|
||||
- **WHEN** the provider list fails and the operator retries
|
||||
- **THEN** the page calls the provider list API again without a full browser reload and renders the returned state
|
||||
|
||||
#### Scenario: Provider status action is pending
|
||||
- **WHEN** an authorized operator confirms enable, disable, or retire
|
||||
- **THEN** only that provider action is disabled, duplicate submission is prevented, and success is shown only after a Platform response
|
||||
|
||||
### Requirement: Session operation tray
|
||||
The console SHALL expose a compact, theme-aware tray for current-session mutation records while clearly distinguishing it from durable Platform job and audit history.
|
||||
|
||||
#### Scenario: Operation fails
|
||||
- **WHEN** a tracked mutation fails
|
||||
- **THEN** the tray shows the intent, safe target label, failure reason, and diagnostic identifier without exposing forbidden values
|
||||
|
||||
#### Scenario: No session operations exist
|
||||
- **WHEN** no mutation has been attempted in the current session
|
||||
- **THEN** the tray remains compact and communicates that durable job and audit history is available on the relevant operational pages
|
||||
|
||||
### Requirement: Theme, responsive, and secret safety
|
||||
All new operations surfaces MUST use existing theme tokens and shared styles, MUST remain coherent in black-mecha and magical-girl themes at desktop and 390px, and MUST not render raw keys, tokens, secret values, host paths, PIDs, sockets, credentials, DSNs, RCON data, or direct Run endpoints.
|
||||
|
||||
#### Scenario: Theme changes
|
||||
- **WHEN** an operator switches between black-mecha and magical-girl themes
|
||||
- **THEN** overview modules, lists, confirmations, progress rows, and the operation tray update atomically through existing theme variables without page-local global decoration
|
||||
|
||||
#### Scenario: Narrow viewport renders operations surfaces
|
||||
- **WHEN** the console is rendered at 390px width
|
||||
- **THEN** controls and text remain within their containers, full-width working surfaces collapse deliberately, and no operational status or action is obscured
|
||||
|
||||
#### Scenario: Narrow viewport navigation stays out of page flow
|
||||
- **WHEN** the console is rendered at 390px width with navigation closed
|
||||
- **THEN** the sidebar, account strip, and icon rail do not consume page height, and a small theme-aware left-edge menu control remains available
|
||||
|
||||
#### Scenario: Operator opens and closes narrow navigation
|
||||
- **WHEN** the operator activates the left-edge control or swipes right from within 28px of the viewport edge
|
||||
- **THEN** an off-canvas vertical menu opens with icons and readable Chinese route labels in the existing order
|
||||
- **AND** Escape, backdrop activation, route selection, or a leftward drawer swipe closes the menu
|
||||
|
||||
#### Scenario: Rendered output is scanned for forbidden fragments
|
||||
- **WHEN** first-party pages are rendered with API-backed fixtures during verification
|
||||
- **THEN** forbidden raw secret, path, process, socket, credential, DSN, RCON, and direct Run endpoint fragments are absent
|
||||
@@ -0,0 +1,69 @@
|
||||
## 1. Shared Operations Contracts
|
||||
|
||||
- [x] 1.1 Add shared frontend view contracts for module availability, job buckets, attention signals, and safe operation targets outside page components.
|
||||
- [x] 1.2 Add pure derivation helpers for active/failed jobs, server attention sorting, and overview module summaries.
|
||||
- [x] 1.3 Add focused tests for job classification, unavailable-module handling, deterministic ordering, and forbidden-field omission.
|
||||
|
||||
## 2. Shared Operations UI
|
||||
|
||||
- [x] 2.1 Add a compact theme-aware current-session operation tray with pending, succeeded, failed, and empty states.
|
||||
- [x] 2.2 Pass the operation tracker through the shell and keep durable Platform job/audit history clearly distinguished from session feedback.
|
||||
- [x] 2.3 Add Escape handling, duplicate-submit protection, and accessible labels to shared management and confirmation dialogs.
|
||||
|
||||
## 3. Operations Overview
|
||||
|
||||
- [x] 3.1 Refactor overview API modules so metrics, usage, providers, and audit events preserve independent loading, ready, empty, and unavailable states.
|
||||
- [x] 3.2 Add actionable endpoint/job/resource/provider status modules and scoped retry/refresh timestamps using only safe Platform projections.
|
||||
- [x] 3.3 Add overview tests covering partial API failure, active/failed jobs, actionable navigation, and read-only session behavior.
|
||||
|
||||
## 4. Server Management
|
||||
|
||||
- [x] 4.1 Add explicit metrics availability/retry and deterministic status/job sorting to the full-width server working surface.
|
||||
- [x] 4.2 Add real active/failed job summaries and recovery navigation without reflowing cards or simulating terminal success.
|
||||
- [x] 4.3 Add tests for metrics failure, job summaries, sorting, and permission-aware create/action controls.
|
||||
|
||||
## 5. Plugin Marketplace
|
||||
|
||||
- [x] 5.1 Add permission-gated confirmed install/enable/disable actions with per-action busy state and persisted-response refresh.
|
||||
- [x] 5.2 Add scoped plugin detail retry that preserves the list summary when detail loading fails.
|
||||
- [x] 5.3 Add tests for confirmation cancellation, duplicate-submit prevention, state failure recovery, and detail retry.
|
||||
|
||||
## 6. User Management
|
||||
|
||||
- [x] 6.1 Remove normal-page development user fallback substitution and render API failure with scoped retry.
|
||||
- [x] 6.2 Add API-backed search, role/status filters, operational summaries, and clear-filter behavior to the full-width user list.
|
||||
- [x] 6.3 Add tests for development API failure, filtering, mutation failure preservation, and platform-admin gating.
|
||||
|
||||
## 7. AI Provider Management
|
||||
|
||||
- [x] 7.1 Replace full-page reload retry with scoped provider loading and preserve explicit empty versus unavailable states.
|
||||
- [x] 7.2 Add confirmed enable/disable/retire actions, provider-scoped busy state, persisted-response refresh, and safe key-presence copy.
|
||||
- [x] 7.3 Add tests for scoped retry, confirmation cancellation, pending duplicate prevention, and failed action recovery.
|
||||
|
||||
## 8. Theme and Responsive Integration
|
||||
|
||||
- [x] 8.1 Add shared theme styles for operations modules, job rows, filters, confirmations, and the operation tray using existing tokens and frame materials.
|
||||
- [x] 8.2 Add responsive rules for full-width working surfaces, dialogs, toolbars, and operation rows at 390px without page-local global decoration.
|
||||
- [x] 8.3 Extend CSS contract tests for theme material reuse, radius limits, and nested-frame safety.
|
||||
- [x] 8.4 Replace the narrow-screen top navigation stack with a theme-aware off-canvas text sidebar, left-edge effect handle, bounded swipe-open/close behavior, and accessible dismissal.
|
||||
- [x] 8.5 Add focused component and CSS contract coverage for mobile labels, drawer state semantics, gesture thresholds, and no-flow layout.
|
||||
|
||||
## 9. Verification
|
||||
|
||||
- [x] 9.1 Run `cd platform_web && npm run typecheck`.
|
||||
- [x] 9.2 Run `cd platform_web && npm test`.
|
||||
- [x] 9.3 Run `cd platform_web && npm run build`.
|
||||
- [x] 9.4 Run browser acceptance for all five first-party areas in black-mecha and magical-girl themes at desktop and 390px, including mobile drawer open/close, confirmation, and failure recovery.
|
||||
- [x] 9.5 Scan rendered first-party pages for forbidden raw key, token, secret, path, PID, socket, credential, DSN, RCON, and direct Run endpoint fragments.
|
||||
- [x] 9.6 Run `scripts/check-structure.sh`, `openspec validate enrich-platform-operations-console --strict`, and both repository `git diff --check` commands, then record evidence.
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- 2026-07-18 15:25 CST: `npm run typecheck`, `npm run build`, and the full Vitest suite passed (24 files, 132 tests).
|
||||
- In-app browser acceptance passed against the real local Platform stack for 首页、服务器管理、插件市场、用户管理、AI 提供商管理 and server detail in `mecha-black` and `magical-girl` at 1440x960 and 390x844 (24 route/theme/viewport checks, zero horizontal overflow, zero console errors).
|
||||
- The 390px sidebar stayed outside page flow (`mainTop=0`, `scrollWidth=390`), opened as a 300px icon-and-Chinese-text drawer, and closed by route selection; both themes were visually inspected.
|
||||
- Confirmation cancellation preserved plugin state and dispatched no mutation. Real plugin persisted responses populated the session operation tray; a duplicate server ID produced a real Platform failure while preserving the form, and a corrected ID retry succeeded. A real dependency validation failure remained traceable in the staged task dialog.
|
||||
- Rendered-page scans found no raw key/token/secret value, host path, PID, socket, credential, DSN, RCON value, or direct Run endpoint across all 24 route states. Safe ordinary labels such as key presence and non-projection notices were intentionally retained.
|
||||
- `scripts/local-debug-smoke.sh` passed using Run-reported capabilities; absent `distribution.build` was verified as unavailable without fake success. `bash -n` and `node --check platform_web/acceptance/browser-acceptance.mjs` passed.
|
||||
- `scripts/check-structure.sh`, `openspec validate enrich-platform-operations-console --strict`, main repository `git diff --check`, and independent Run repository `git diff --check` all passed.
|
||||
- Structured browser evidence: `/private/tmp/browser-local-debug-acceptance-9k/browser-acceptance/item-9-evidence.json`.
|
||||
Reference in New Issue
Block a user