report: storebound report writes one shareable, self-contained readiness page (.storebound/reports/readiness-<date>.html; --md, --json, --no-open, --offline, --out) from scan, check and validate: a verdict per store (Ready to submit / N blockers / Not checked with the reason), findings per store by severity with guideline, evidence, fix and console button, the owner's compliance questions as a checklist, secrets masked; storebound.dev look, light / dark, print; desktop Checks > Report (same code path, opens through project_reveal) and its Markdown export on the same renderer; read-only MCP tool report

This commit is contained in:
CRTkafa 2026-10-18 01:42:03 +08:00
parent 6d95ea00f5
commit af349b3db1
18 changed files with 792 additions and 12 deletions

View file

@ -174,9 +174,14 @@ pub fn project_relative(rel: &str) -> Option<std::path::PathBuf> {
Some(p.to_path_buf())
}
/// What `project_reveal` may open (not only show in the file manager): a folder, or the gallery page storebound writes.
/// What `project_reveal` may open (not only show in the file manager): a folder, the gallery page storebound writes,
/// or a readiness report page of `storebound report` (.storebound/reports/readiness-*.html, no scripts in it).
pub fn openable(rel: &std::path::Path, is_dir: bool) -> bool {
is_dir || rel.file_name().and_then(|n| n.to_str()) == Some("index.html")
if is_dir || rel.file_name().and_then(|n| n.to_str()) == Some("index.html") {
return true;
}
let parts: Vec<&str> = rel.components().filter_map(|c| c.as_os_str().to_str()).collect();
matches!(parts.as_slice(), [".storebound", "reports", name] if name.starts_with("readiness-") && name.ends_with(".html") && name.len() <= 80)
}
/// Hosts `open_external` may open in the browser: the two store consoles and storebound's own site.