Skip to content
Clone

refactor(project): refresh crate across features, authz and metrics

zhenyi committed
parent f1f6c66 commit a1591c8 Browse files

4 files changed

+1 −38

File tree 4
Modified lib/project/features/authz.rs View lib/project/features/authz.rs
@@ -11,12 +11,6 @@
1111};
1212use crate::service::ProjectService;
1313
14/// Resolve a user's effective permissions for a project.
15///
16/// Two-tier check:
17/// 1. Caller must be an active space member (delegated to space::features::authz).
18/// 2. Project role is looked up in `project_members` (cached). Non-members get
19/// read-only `Viewer` defaults.
2014pub async fn resolve(
2115 svc: &ProjectService,
2216 user_id: Uuid,
@@ -36,7 +30,6 @@
3630 Ok(role_to_permissions(role))
3731}
3832
39/// Same as [`resolve`] but caches the role lookup.
4033pub async fn resolve_with_cache(
4134 svc: &ProjectService,
4235 user_id: Uuid,
@@ -77,7 +70,6 @@
7770 Ok(role_to_permissions(role))
7871}
7972
80/// Require a specific permission on a project; short-circuits with Forbidden.
8173pub async fn require(
8274 svc: &ProjectService,
8375 user_id: Uuid,
Modified lib/project/handler/middleware/metrics.rs View lib/project/handler/middleware/metrics.rs
@@ -2,12 +2,6 @@
22use axum::middleware::Next;
33use axum::response::Response;
44
5/// HTTP-level metrics layer for the `project` crate.
6///
7/// Emits `project_http_requests_total{route,method,status_class}` (counter) and
8/// `project_http_request_duration_seconds{route,method,status_class}` (histogram)
9/// on every request that traverses the router. Uses `MatchedPath` so the
10/// `route` label stays low-cardinality (no space-id path params).
115pub async fn metrics_layer(req: Request, next: Next) -> Response {
126 crate::metrics::ensure_described();
137
Modified lib/project/error.rs View lib/project/error.rs
@@ -86,8 +86,7 @@
8686 )
8787 }
8888
89 /// Bounded label for metrics. Keep stable and low-cardinality.
90 pub fn error_kind(&self) -> &'static str {
89 pub fn error_kind(&self) -> &'static str {
9190 match self {
9291 ProjectError::BadRequest(_) => "bad_request",
9392 ProjectError::Unauthorized(_) => "unauthorized",
Modified lib/project/metrics.rs View lib/project/metrics.rs
@@ -1,63 +1,47 @@
1//! Tracing layer for the `project` crate.
2//!
3//! Emits metrics through the `metrics` facade. No exporter is installed here;
4//! the host binary is responsible for binding a recorder. All labels are
5//! bounded to keep cardinality low (no `space_id`/`project_id`/`user_id`).
6
71use std::time::Instant;
82
93use metrics::{counter, describe_counter, describe_histogram, histogram};
104
115use crate::error::ProjectError;
126
13// ── Feature constants (one per usecase) ───────────────────────────────────
147
15// lifecycle
168pub const FEATURE_PROJECTS_CREATE: &str = "projects_create";
179pub const FEATURE_PROJECTS_GET: &str = "projects_get";
1810pub const FEATURE_PROJECTS_UPDATE: &str = "projects_update";
1911pub const FEATURE_PROJECTS_DELETE: &str = "projects_delete";
2012pub const FEATURE_PROJECTS_LIST: &str = "projects_list";
2113
22// members
2314pub const FEATURE_PROJECT_MEMBERS_ADD: &str = "project_members_add";
2415pub const FEATURE_PROJECT_MEMBERS_GET: &str = "project_members_get";
2516pub const FEATURE_PROJECT_MEMBERS_UPDATE: &str = "project_members_update";
2617pub const FEATURE_PROJECT_MEMBERS_REMOVE: &str = "project_members_remove";
2718pub const FEATURE_PROJECT_MEMBERS_LIST: &str = "project_members_list";
2819
29// views
3020pub const FEATURE_PROJECT_VIEWS_CREATE: &str = "project_views_create";
3121pub const FEATURE_PROJECT_VIEWS_GET: &str = "project_views_get";
3222pub const FEATURE_PROJECT_VIEWS_UPDATE: &str = "project_views_update";
3323pub const FEATURE_PROJECT_VIEWS_DELETE: &str = "project_views_delete";
3424pub const FEATURE_PROJECT_VIEWS_LIST: &str = "project_views_list";
3525
36// documents
3726pub const FEATURE_PROJECT_DOCS_CREATE: &str = "project_docs_create";
3827pub const FEATURE_PROJECT_DOCS_GET: &str = "project_docs_get";
3928pub const FEATURE_PROJECT_DOCS_UPDATE: &str = "project_docs_update";
4029pub const FEATURE_PROJECT_DOCS_DELETE: &str = "project_docs_delete";
4130pub const FEATURE_PROJECT_DOCS_LIST: &str = "project_docs_list";
4231
43// links
4432pub const FEATURE_PROJECT_LINKS_ADD: &str = "project_links_add";
4533pub const FEATURE_PROJECT_LINKS_REMOVE: &str = "project_links_remove";
4634pub const FEATURE_PROJECT_LINKS_LIST: &str = "project_links_list";
4735
48// favorites
4936pub const FEATURE_PROJECT_FAVORITES_ADD: &str = "project_favorites_add";
5037pub const FEATURE_PROJECT_FAVORITES_REMOVE: &str = "project_favorites_remove";
5138pub const FEATURE_PROJECT_FAVORITES_LIST: &str = "project_favorites_list";
5239
53// activities
5440pub const FEATURE_PROJECT_ACTIVITIES_LIST: &str = "project_activities_list";
5541
56// ── Outcome labels (bounded enums) ────────────────────────────────────────
5742
5843pub const OUTCOME_SUCCESS: &str = "success";
5944
60// ── Metric description registration (Once) ────────────────────────────────
6145
6246static DESCRIBE_ONCE: std::sync::Once = std::sync::Once::new();
6347
@@ -94,9 +78,7 @@
9478 );
9579}
9680
97// ── Timer (RAII) ──────────────────────────────────────────────────────────
9881
99/// Records the usecase execution duration on drop.
10082pub struct Timer {
10183 pub feature: &'static str,
10284 pub start: Instant,
@@ -123,10 +105,7 @@
123105 }
124106}
125107
126// ── Generic outcome counter ───────────────────────────────────────────────
127108
128/// Bump invocation counter (always) and, on `Err`, an error counter labeled
129/// by `ProjectError::error_kind()`. Drop semantics of `_timer` capture latency.
130109pub fn record_outcome<T>(feature: &'static str, result: &Result<T, ProjectError>) {
131110 match result {
132111 Ok(_) => {
@@ -155,7 +134,6 @@
155134 }
156135}
157136
158// ── Project create helper ─────────────────────────────────────────────────
159137
160138#[derive(Debug, Clone, Copy)]
161139pub enum ProjectCreateOutcome {