feat(modules): no-provider plan check + read-only extension-points ls (§5.5 C4)
- apply: `check_extension_points_provided` (app nodes) — every EP visible on
the app's chain (its own + inherited) must have a provider: a same-apply
module, or one resolvable up-chain (override or default body). Else a clean
`pic plan` error instead of a runtime failure. Single-node only (the tree
path leans on the runtime backstop, like the dangling-import check).
- read-only surface: `extension_point_report` + `ExtensionPointInfo`;
`GET /{apps|groups}/{id}/extension-points` (AppRead / GroupScriptsRead);
`pic extension-points ls --app|--group` showing declared-vs-inherited + the
resolved provider (`app override` / `inherited default` / `unset`).
- `pic pull` round-trips an app's OWN declared EPs (filtered `declared_here`),
so pull→plan stays idempotent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1305,6 +1305,35 @@ impl NodeKind {
|
||||
}
|
||||
}
|
||||
|
||||
/// One row of the §5.5 extension-point report.
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ExtensionPointInfoDto {
|
||||
pub name: String,
|
||||
#[serde(default)]
|
||||
pub declared_here: bool,
|
||||
#[serde(default)]
|
||||
pub provider: Option<String>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// `GET /api/v1/admin/{apps|groups}/{ident}/extension-points`.
|
||||
pub async fn extension_points_list(
|
||||
&self,
|
||||
kind: NodeKind,
|
||||
ident: &str,
|
||||
) -> Result<Vec<ExtensionPointInfoDto>> {
|
||||
let ident = seg(ident);
|
||||
let resp = self
|
||||
.request(
|
||||
Method::GET,
|
||||
&format!("/api/v1/admin/{}/{ident}/extension-points", kind.path()),
|
||||
)
|
||||
.send()
|
||||
.await?;
|
||||
decode(resp).await
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- DTOs (CLI-local, wire-shape-matched) ----------
|
||||
|
||||
/// Response of `POST .../plan`: per-resource diffs grouped by kind.
|
||||
|
||||
Reference in New Issue
Block a user