moonseal

Generate CycloneDX SBOMs and audit MoonBit projects for release readiness and open-source compliance.

sbom
cyclonedx
license
supply-chain
security
moon add liyun/moonseal@0.2.1
Download zip
Author
Version
0.2.1
License
Apache-2.0
Last updated
7 days ago
Downloads
2

Dependencies

README

#MoonSeal

Seal your MoonBit supply chain.

CI License

MoonSeal is a MoonBit-native release-readiness auditor and CycloneDX SBOM generator. It understands MoonBit manifests and Mooncakes package coordinates, then turns repository metadata into actionable findings and a standard software bill of materials.

中文简介: MoonSeal 是面向 MoonBit 项目的软件供应链清单与开源合规 工具。它可以检查项目发布条件、许可证声明和依赖信息,并生成 CycloneDX 1.6 SBOM。

#Why MoonSeal?

General-purpose scanners do not understand MoonBit's current moon.mod format, its legacy moon.mod.json format, or pkg:mooncakes package URLs. MoonSeal provides a small, deterministic core library plus a practical CLI designed for MoonBit repositories and CI pipelines.

#Capabilities

  • Parse current and legacy MoonBit module manifests.
  • Extract module metadata and Mooncakes dependencies.
  • Validate common SPDX identifiers and compound expressions.
  • Detect common license texts and declaration mismatches.
  • Check README, LICENSE, repository URL, CI, changelog, and source presence.
  • Enforce repository-specific policy from moonseal-policy.json.
  • Analyze dependency pinning, coordinates, duplicates, and version conflicts.
  • Produce text, JSON, Markdown, and SARIF audit reports.
  • Generate deterministic CycloneDX 1.6 SBOM documents.
  • Compare audit baselines and identify regressions.
  • Generate in-toto/SLSA provenance statements.
  • Run on the WebAssembly backend; support native builds where available.

#Functional boundaries

MoonSeal is a deterministic release-readiness library and reference CLI. It analyzes repository metadata supplied by the caller and emits interoperable reports. It does not download packages, query vulnerability databases, provide legal conclusions, sign artifacts, or upload reports. Network enrichment and cryptographic signing belong in adapters built on top of the core library.

This boundary keeps audits reproducible offline while leaving clear extension points for Mooncakes metadata, vulnerability feeds, and CI attestations.

#Installation

Install the current MoonBit toolchain. After version 0.2.1 is published on Mooncakes, library consumers can add it with:

moon add liyun/moonseal@0.2.1

To use the reference CLI, clone this repository and run the commands below.

#Quick start

Clone the public repository, resolve its pinned dependencies, and run the self-audit example:

moon update moon run cmd/main scan .

Example output:

MoonSeal audit: liyun/moonseal Score: 100/100 Source: 4362 MoonBit lines | 0 errors | 0 warnings READY No release-readiness issues found.

Generate a CycloneDX SBOM:

moon run cmd/main sbom . -o moonseal.cdx.json

See examples/moonseal.cdx.json for a schema-validated example generated from this repository.

Use MoonSeal as a blocking CI check:

moon run cmd/main check .

Get a machine-readable report:

moon run cmd/main scan . --json

Generate a Markdown build summary:

moon run cmd/main scan . --markdown

Generate a SARIF report for code-scanning platforms:

moon run cmd/main scan . --sarif

Analyze direct Mooncakes dependencies:

moon run cmd/main dependencies .

Enforce the checked-in repository policy:

moon run cmd/main policy . --policy moonseal-policy.json

#Commands

CommandPurpose
moonseal scan [PATH] [--json \| --markdown \| --sarif]Audit a project and print findings
moonseal check [PATH]Audit and fail if blocking findings exist
moonseal sbom [PATH] [-o FILE]Generate a CycloneDX 1.6 SBOM
moonseal dependencies [PATH] [--json]Analyze dependency metadata
moonseal policy [PATH] [--policy FILE] [--json]Enforce repository policy
moonseal helpShow command help

During development, replace moonseal with moon run cmd/main.

#Audit rules

CodeSeverityCheck
MS001ErrorModule name is present
MS002ErrorModule version is present
MS003ErrorSPDX license declaration is present
MS004ErrorSPDX expression is recognized
MS005WarningRepository URL is present
MS006ErrorLicense file exists
MS007ErrorREADME exists
MS008WarningGitHub Actions workflow exists
MS009WarningChangelog exists
MS010Info.gitignore exists
MS011ErrorDeclared and detected licenses agree
MS012WarningLicense text can be identified
MS013ErrorMoonBit source is present
MS014WarningRepository URL uses a recognized Git transport

MoonSeal provides engineering signals, not legal advice. A passing report does not replace legal review.

#Library API

The core package has no file-system side effects. Its main public functions are:

  • parse_manifest(path, text)
  • normalize_license(identifier)
  • valid_spdx(expression)
  • detect_license(text)
  • audit(facts)
  • evaluate_policy(policy, facts, report)
  • analyze_dependencies(project)
  • render_text(report), render_json(report), and render_sarif(report)
  • cyclonedx(project) and cyclonedx_string(project)
  • compare_reports(previous, current)
  • provenance(project, options)

See the architecture guide for the package boundaries.

#Development and tests

moon fmt moon check --target wasm -d moon test --target wasm moon build --target wasm --release moon run --target wasm cmd/main check .

The tests cover both manifest formats, dependency extraction, SPDX validation, license detection, audit scoring, report generation, and CycloneDX output. See the MVP status and reproduction checklist for the current delivery boundary.

Reviewers can use the dedicated evidence documents:

#Maintenance

Bug reports and feature proposals use the GitHub issue forms. Contributions follow CONTRIBUTING.md and must include tests for behavior changes. User-visible changes are recorded in CHANGELOG.md, and published versions use immutable semantic-version tags.

#Competition

MoonSeal is being developed for the 2026 MoonBit 国产基础软件生态开源大赛 8 月黑客松. The competition applicant and primary maintainer is 马昀昀, who uses the GitHub account @liyun6666. Therefore, the applicant name and the repository owner/commit identity refer to the same contributor. Contact details are intentionally kept out of the public package.

#License

Apache-2.0. See LICENSE and THIRD_PARTY.md.

#
AuditDelta

pub(all) struct AuditDelta {
project_name : String
previous_score : Int
current_score : Int
previous_ready : Bool
current_ready : Bool
added : Array[Finding]
resolved : Array[Finding]
unchanged : Array[Finding]
changed : Array[FindingChange]
} derive(Eq,
Debug
)

#
AuditDelta::has_changes

fn AuditDelta::has_changes(self : AuditDelta) -> Bool

#
AuditDelta::improved

fn AuditDelta::improved(self : AuditDelta) -> Bool

#
AuditDelta::regressed

fn AuditDelta::regressed(self : AuditDelta) -> Bool

#
AuditDelta::score_change

fn AuditDelta::score_change(self : AuditDelta) -> Int

#
AuditPolicy

pub(all) struct AuditPolicy {
minimum_score : Int
minimum_source_lines : Int
maximum_warnings : Int
maximum_dependencies : Int
require_repository : Bool
require_ci : Bool
require_changelog : Bool
require_security_policy : Bool
require_pinned_dependencies : Bool
allowed_licenses : Array[String]
denied_licenses : Array[String]
required_files : Array[String]
} derive(Eq,
Debug
)

Repository-specific release policy loaded from moonseal-policy.json.

#
AuditReport

pub(all) struct AuditReport {
project : Project
findings : Array[Finding]
moonbit_source_lines : Int
score : Int
} derive(Eq,
Debug
)

Complete deterministic result of a MoonSeal audit.

#
AuditReport::error_count

fn AuditReport::error_count(self : AuditReport) -> Int

#
AuditReport::is_ready

fn AuditReport::is_ready(self : AuditReport) -> Bool

#
AuditReport::warning_count

fn AuditReport::warning_count(self : AuditReport) -> Int

#
Dependency

pub(all) struct Dependency {
name : String
version : String
} derive(Eq,
Debug
)

A MoonBit module dependency discovered in the module manifest.

#
DependencyHealth

pub(all) struct DependencyHealth {
total : Int
pinned : Int
unpinned : Int
unique : Int
namespaces : Array[NamespaceCount]
issues : Array[DependencyIssue]
} derive(Eq,
Debug
)

#
DependencyHealth::error_count

fn DependencyHealth::error_count(self : DependencyHealth) -> Int

#
DependencyHealth::is_healthy

fn DependencyHealth::is_healthy(self : DependencyHealth) -> Bool

#
DependencyHealth::warning_count

fn DependencyHealth::warning_count(self : DependencyHealth) -> Int

#
DependencyHealthSeverity

pub enum DependencyHealthSeverity {
DependencyInfo
DependencyWarning
DependencyError
} derive(Eq,
Debug
)

#
DependencyIssue

pub(all) struct DependencyIssue {
severity : DependencyHealthSeverity
code : String
dependency : String
message : String
} derive(Eq,
Debug
)

#
Finding

pub(all) struct Finding {
severity : Severity
code : String
path : String
message : String
} derive(Eq,
Debug
)

One actionable release-readiness or compliance observation.

#
FindingChange

pub(all) struct FindingChange {
code : String
path : String
previous_severity : Severity
current_severity : Severity
previous_message : String
current_message : String
} derive(Eq,
Debug
)

#
NamespaceCount

pub(all) struct NamespaceCount {
scope : String
count : Int
} derive(Eq,
Debug
)

#
PolicyResult

pub(all) struct PolicyResult {
policy : AuditPolicy
violations : Array[PolicyViolation]
} derive(Eq,
Debug
)

Result of applying repository policy to an audit.

#
PolicyResult::is_allowed

fn PolicyResult::is_allowed(self : PolicyResult) -> Bool

#
PolicyViolation

pub(all) struct PolicyViolation {
code : String
path : String
message : String
} derive(Eq,
Debug
)

One policy-specific violation. These use the MP prefix so they remain distinguishable from built-in MS audit findings.

#
Project

pub(all) struct Project {
name : String
version : String
license : String
repository : String
dependencies : Array[Dependency]
} derive(Eq,
Debug
)

Metadata parsed from moon.mod or legacy moon.mod.json.

#
ProvenanceOptions

pub(all) struct ProvenanceOptions {
builder_id : String
build_type : String
source_uri : String
revision : String
subject_digest : String
invocation_id : String
started_on : String
finished_on : String
reproducible : Bool
} derive(Eq,
Debug
)

#
ScanFacts

pub(all) struct ScanFacts {
project : Project
files : Array[String]
moonbit_source_lines : Int
license_text : String?
} derive(Eq,
Debug
)

File-system facts collected by the CLI and audited by the pure library.

#
Severity

pub(all) enum Severity {
Info
Warning
Error
} derive(Eq,
Debug
)

Severity assigned to an audit finding.

#
Severity::label

fn Severity::label(self : Severity) -> String

#
analyze_dependencies

fn analyze_dependencies(project : Project) -> DependencyHealth

Analyze direct Mooncakes dependencies for reproducibility and metadata quality. The analysis is deterministic and does not require network access.

#
audit

fn audit(facts : ScanFacts) -> AuditReport

Audit pure scan facts. This function performs no file-system access and is therefore portable and deterministic.

#
compare_reports

fn compare_reports(previous : AuditReport, current : AuditReport) -> AuditDelta

Compare two audit reports without depending on timestamps or filesystem state. Findings are matched by stable rule code and path.

#
cyclonedx

fn cyclonedx(project : Project) -> Json

Generate a deterministic CycloneDX 1.6 SBOM as JSON.

#
cyclonedx_string

fn cyclonedx_string(project : Project, indent? : Int) -> String

#
default_policy

fn default_policy() -> AuditPolicy

#
default_provenance_options

fn default_provenance_options() -> ProvenanceOptions

#
delta_json

fn delta_json(delta : AuditDelta) -> Json

#
dependency_health_json

fn dependency_health_json(health : DependencyHealth) -> Json

#
dependency_inventory

fn dependency_inventory(project : Project) -> Json

#
dependency_purl

fn dependency_purl(dependency : Dependency) -> String

#
detect_license

fn detect_license(text : StringView) -> String?

Identify common license texts without relying on file names.

#
evaluate_policy

fn evaluate_policy(policy : AuditPolicy, facts : ScanFacts, report : AuditReport) -> PolicyResult

Apply repository policy to already-collected facts and an audit report.

#
normalize_license

fn normalize_license(identifier : StringView) -> String

Normalize common aliases to SPDX identifiers.

#
parse_manifest

fn parse_manifest(path : StringView, text : StringView) -> Project raise

Parse either supported module manifest based on its file name.

#
parse_moon_mod

fn parse_moon_mod(text : StringView) -> Project

Parse the current TOML-like MoonBit module format.

#
parse_moon_mod_json

fn parse_moon_mod_json(text : StringView) -> Project raise

Parse the legacy JSON MoonBit module format.

#
parse_policy

fn parse_policy(text : StringView) -> AuditPolicy raise

Parse a MoonSeal policy document. Unknown keys are deliberately ignored so that policy files remain forwards compatible.

#
provenance

fn provenance(project : Project, options : ProvenanceOptions) -> Json

Create an in-toto Statement carrying a SLSA Provenance v1 predicate. The caller supplies revision and digest values because the portable core does not read Git state or hash build artifacts.

#
provenance_warnings

fn provenance_warnings(project : Project, options : ProvenanceOptions) -> Array[String]

Validate data required for a useful, publishable provenance statement.

#
render_delta_json

fn render_delta_json(delta : AuditDelta, indent? : Int) -> String

#
render_delta_markdown

fn render_delta_markdown(delta : AuditDelta) -> String

#
render_delta_text

fn render_delta_text(delta : AuditDelta) -> String

#
render_dependency_json

fn render_dependency_json(health : DependencyHealth, indent? : Int) -> String

#
render_dependency_text

fn render_dependency_text(health : DependencyHealth) -> String

#
render_json

fn render_json(report : AuditReport, indent? : Int) -> String

Render a machine-readable report suitable for CI.

#
render_markdown

fn render_markdown(report : AuditReport) -> String

Render an audit report for issue trackers, pull requests, and build summaries.

#
render_policy_json

fn render_policy_json(result : PolicyResult, indent? : Int) -> String

#
render_policy_text

fn render_policy_text(result : PolicyResult) -> String

#
render_provenance

fn render_provenance(project : Project, options : ProvenanceOptions, indent? : Int) -> String

#
render_provenance_warnings

fn render_provenance_warnings(project : Project, options : ProvenanceOptions) -> String

#
render_sarif

fn render_sarif(report : AuditReport, indent? : Int) -> String

#
render_text

fn render_text(report : AuditReport) -> String

Render a compact human-readable audit report.

#
sarif

fn sarif(report : AuditReport) -> Json

Convert an audit report to SARIF 2.1.0 for GitHub Code Scanning and other interoperable static-analysis consumers.

#
valid_spdx

fn valid_spdx(expression : StringView) -> Bool

Validate a practical subset of SPDX expressions: identifiers joined by AND or OR, with optional grouping parentheses.