Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ engines are not bundled; see the [browser requirements](https://github.com/OctoS
| `docs/FIRST-APP.md` | A first-app walkthrough for a card app or a script app: create, run, capture and check. |
| `docs/SUBMITTING.md` | The submission's four stages, who runs each `hub` command, and every step from repository layout to publication. |
| `docs/PUBLISHING.md` | The reference: gate rules; capabilities and who serves them; manifest, listing and tool fields; host services; `hub` commands; signing. |
| `docs/ERROR-CODES.md` | The gate's stable error codes and one-line fixes, in its text report and `--json`, for tools that repair bundles. |
| `docs/GITHUB-PUBLISHING.md` | Admin-authorized GitHub signing, exact candidate review and v2 migration. |
| `docs/HOST-API.md` | Declaring the host APIs an app needs, `runtime` discovery and what today's hosts implement. |
| `docs/ICONS.md` | Canonical icon ownership, export constraints and visual review. |
Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Linux 需要 GTK 3/WebKitGTK 和 X11/XWayland,Windows 需要 WebView2。这些
| `docs/FIRST-APP.md` | 第一个应用(卡片应用或脚本应用)的分步教程:创建、运行、截图与检查。 |
| `docs/SUBMITTING.md` | 提交流程的四个阶段、每个 `hub` 命令由谁运行,以及从仓库结构到发布的每一步。 |
| `docs/PUBLISHING.md` | 参考文档:准入规则;能力及其提供方;清单、商店信息和工具的字段;宿主服务;`hub` 命令;签名。 |
| `docs/ERROR-CODES.md` | 准入检查的稳定错误码与一行修复建议(英文),出现在文本报告与 `--json` 中,供修复应用包的工具读取。 |
| `docs/GITHUB-PUBLISHING.md` | 管理员授权的 GitHub 签名、确切候选审核及 v2 迁移。 |
| `docs/HOST-API.md` | 声明应用需要的宿主 API、用 `runtime` 发现宿主 API,以及目前各宿主实现了哪些 API。 |
| `docs/ICONS.md` | 规范图标的归属、导出约束与视觉评审。 |
Expand Down
18 changes: 14 additions & 4 deletions crates/app-hub/src/admission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ fn font_resource(value: &Value, path: &str, tokens: &Value, out: &mut Vec<Resour
Some(Value::Null) => {},
Some(Value::String(target)) if target.is_empty() => {},
_ => findings.push(Finding::at("resource-invalid", path,
"font_src must be a bundled font path, a supported built-in font, or one token resolving to a string")),
"font_src must be a bundled font path, a supported built-in font, or one token resolving to a string")
.coded("hub-font-invalid", "set font_src to a bundled font path, a supported built-in font, or one token resolving to a string")),
}
}

Expand Down Expand Up @@ -229,11 +230,17 @@ pub fn validate(root: &Path, files: &[BundleFile]) -> (Vec<Finding>, Vec<Resourc
_ => Ok(()),
};
if let Err(error) = result {
findings.push(Finding::at("contents-invalid", name.as_str(), error));
findings.push(Finding::at("contents-invalid", name.as_str(), error).coded(
"hub-contents-invalid",
"the file is not what its extension says: repair or re-export it (UTF-8 text within the size limit, a decodable image, a sized scriptless SVG, an admissible wasm)",
));
}
}
if let Err((path, error)) = validate_entry(root) {
findings.push(Finding::at("entry", path, error));
findings.push(Finding::at("entry", path, error).coded(
"hub-entry-invalid",
"add an entry the runtime can start: main.splash (a script app) or page.card with its kit (a card)",
));
}
for reference in &refs {
if matches!(reference.kind, ResourceKind::DisplayUrl) {
Expand All @@ -258,7 +265,10 @@ pub fn validate(root: &Path, files: &[BundleFile]) -> (Vec<Finding>, Vec<Resourc
}
});
if let Err(error) = result {
findings.push(Finding::at("resource-invalid", &reference.path, error));
findings.push(Finding::at("resource-invalid", &reference.path, error).coded(
"hub-resource-missing",
"ship the referenced file at that bundle-relative path, or drop the reference",
));
}
}
(findings, refs)
Expand Down
22 changes: 12 additions & 10 deletions crates/app-hub/src/advisories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::path::Path;
use semver::{Version, VersionReq};
use serde::Deserialize;

use crate::gate::{Finding, Severity};
use crate::gate::Finding;

/// The largest advisory file read.
const MAX_ADVISORY_BYTES: u64 = 256 << 10;
Expand Down Expand Up @@ -145,15 +145,17 @@ pub fn findings(bundle: &Path, db: &Path) -> Result<Vec<Finding>, String> {
} else {
format!("fixed in {}", advisory.patched.join(" or "))
};
findings.push(Finding {
severity: Severity::Warning,
check: "advisories",
detail: format!(
"{name} includes {} {}, which {} reports as {what}: {}; {fixed}",
listed.name, listed.version, advisory.id, advisory.title
),
path: Some(name.clone()),
});
findings.push(
Finding::warn_at(
"advisories",
name.clone(),
format!(
"{name} includes {} {}, which {} reports as {what}: {}; {fixed}",
listed.name, listed.version, advisory.id, advisory.title
),
)
.coded("hub-crate-advisory", "upgrade the crate to a fixed version and rebuild the component, then re-run with --advisory-db to confirm"),
);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/app-hub/src/bin/hub-usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ publish, human-review stops it until --reviewed) and writes

check is the gate: a publisher runs it before submitting, the hub runs the
same code after. publish re-runs it, copies the bundle into the artifact
store and signs the catalog.
store and signs the catalog. Each finding carries a stable code and a one-line
fix (docs/ERROR-CODES.md), in the text report and in --json.

Shared components (App Hub ADR 0003) are published like apps: the release's
GitHub workflow runs component-prepare, attests the subject and runs
Expand Down
4 changes: 3 additions & 1 deletion crates/app-hub/src/bin/hub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ fn run() -> Result<(), String> {
// the same shape, for tools that read --json.
if has("json") {
println!("{}", serde_json::json!({"schema": 1, "stage": "structural", "passed": false,
"findings": [{"severity": "refusal", "check": "bundle-invalid", "detail": error}]}));
"findings": [{"severity": "refusal", "check": "bundle-invalid", "detail": error,
"code": "hub-bundle-invalid",
"hint": "the bundle is unreadable: manifest.json must be present, valid JSON the manifest schema accepts (schema, id, version, name)"}]}));
}
return Err(error);
}
Expand Down
Loading