feat(suppress): pic suppress ls --app + dangling-suppress warning (§11 tail S4)
Visibility + typo guard.
- `pic suppress ls --app <a>` — read-only (kind, reference):
ApplyService::suppression_report(App) → GET /apps/{id}/suppressions
(viewer-tier AppRead), client + cmd + main.rs wiring.
- Dangling-suppress warning: at apply, a suppress reference that matches no
inherited template on the app's chain (no ancestor-group trigger bound to
that script name / no ancestor-group route at that path) emits an
ApplyReport warning — the suppression silently does nothing otherwise.
Soft (never fails the apply), reusing the existing warnings channel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,8 +18,8 @@ use serde_json::json;
|
||||
use crate::app_repo::AppRepository;
|
||||
use crate::apply_service::{
|
||||
ApplyError, ApplyOwner, ApplyReport, ApplyService, Bundle, BundleTrigger, CollectionInfo,
|
||||
ExtensionPointInfo, NodeKind, PlanResult, RouteTemplateInfo, TreeBundle, TreePlanResult,
|
||||
TriggerTemplateInfo,
|
||||
ExtensionPointInfo, NodeKind, PlanResult, RouteTemplateInfo, SuppressionInfo, TreeBundle,
|
||||
TreePlanResult, TriggerTemplateInfo,
|
||||
};
|
||||
use crate::authz::{require, AuthzDenied, Capability};
|
||||
use crate::group_repo::GroupRepository;
|
||||
@@ -44,9 +44,26 @@ pub fn apply_router(service: ApplyService) -> Router {
|
||||
.route("/groups/{id}/collections", get(group_collections_handler))
|
||||
.route("/groups/{id}/triggers", get(group_triggers_handler))
|
||||
.route("/groups/{id}/routes", get(group_routes_handler))
|
||||
.route("/apps/{id}/suppressions", get(app_suppressions_handler))
|
||||
.with_state(service)
|
||||
}
|
||||
|
||||
/// Read-only §11 tail suppression report for an app: the inherited templates it
|
||||
/// declines (`target_kind`, `reference`). Viewer-tier `AppRead`. Backs
|
||||
/// `pic suppress ls --app`.
|
||||
async fn app_suppressions_handler(
|
||||
State(svc): State<ApplyService>,
|
||||
Extension(principal): Extension<Principal>,
|
||||
Path(id_or_slug): Path<String>,
|
||||
) -> Result<Json<Vec<SuppressionInfo>>, ApplyError> {
|
||||
let app_id = resolve_app_id(svc.apps.as_ref(), &id_or_slug).await?;
|
||||
require(svc.authz.as_ref(), &principal, Capability::AppRead(app_id))
|
||||
.await
|
||||
.map_err(map_authz)?;
|
||||
let report = svc.suppression_report(ApplyOwner::App(app_id)).await?;
|
||||
Ok(Json(report))
|
||||
}
|
||||
|
||||
/// Read-only §11 tail route-template report for a group: its own declared route
|
||||
/// templates (method, host, path, handler script, dispatch, enabled). Viewer-
|
||||
/// tier read. Backs `pic routes ls --group`.
|
||||
|
||||
Reference in New Issue
Block a user