目录

MoonModGuard

MoonModGuard is a MoonBit project manifest and supply-chain policy auditor.

What It Does

MoonModGuard parses moon.mod and moon.pkg text, extracts module metadata and package imports, builds an in-memory project model, evaluates supply-chain policy risks, and renders a deterministic Markdown audit report.

The first version is deliberately dependency-free and accepts explicit strings or snapshots instead of scanning the filesystem. This keeps the core portable and testable while leaving room for later CI and workspace integrations.

Installation

moon add Noverberrain/moonmodguard

Why This Exists

MoonBit projects rely on compact manifest files for package identity, dependencies, metadata, and publication readiness. A small auditor can help maintainers check whether a package is ready to publish, whether metadata is complete, and whether dependency declarations match a local policy.

MoonModGuard targets software analysis and engineering quality workflows:

  • package release readiness checks
  • contest repository review
  • classroom or team repository governance
  • dependency policy demonstration
  • future CI or package registry audit integration

Features

  • Parse scalar fields from moon.mod: name, version, license, readme, repository, description.
  • Parse array fields such as keywords = [ "audit", "moonbit" ].
  • Parse import blocks from moon.mod and moon.pkg.
  • Build a project model from module and package manifests.
  • Evaluate policy diagnostics for missing metadata, disallowed licenses, unknown dependency prefixes, and duplicate dependencies.
  • Render a deterministic Markdown report.
  • Provide a runnable CLI demo.

Quick Start

moon test
moon run cmd/main

Example CLI output:

MoonModGuard demo
project=wyc060514/moonmodguard
dependencies=2
risks=0
--- markdown ---
# MoonModGuard Audit Report

API Example

///|
test "audit a project" {
  let manifest = match @moonmodguard.parse_mod(
    "name = \"wyc060514/tool\"\nlicense = \"Apache-2.0\"\nreadme = \"README.md\"\nrepository = \"https://example.test/repo\"",
  ) {
    Ok(value) => value
    Err(err) => fail(@moonmodguard.format_error(err))
  }
  let report = @moonmodguard.evaluate_policy(
    @moonmodguard.project_from(manifest, []),
    @moonmodguard.default_policy(),
  )
  assert_eq(report.risk_count, 0)
}

Public API:

  • parse_mod(input : String) -> Result[ModuleManifest, GuardError]
  • parse_pkg(input : String) -> Result[PackageManifest, GuardError]
  • project_from(manifest : ModuleManifest, packages : Array[PackageManifest]) -> ProjectModel
  • scan_project(snapshot : ProjectSnapshot) -> AuditReport
  • default_policy() -> Policy
  • evaluate_policy(project : ProjectModel, policy : Policy) -> AuditReport
  • render_markdown(report : AuditReport) -> String
  • format_error(err : GuardError) -> String

Consumer Guide

CLI Usage

# Audit a moon.mod file, output Markdown report
moon run cmd/main -- moon.mod

# Output JSON instead of Markdown
moon run cmd/main -- moon.mod --json

# Use EnhancedPolicy with trust grading
moon run cmd/main -- moon.mod --enhanced

EnhancedPolicy with Trust Grading

let manifest = match @moonmodguard.parse_mod(mod_text) {
  Ok(m) => m
  Err(_) => abort("parse error")
}
let project = @moonmodguard.project_from(manifest, [])
let report = @moonmodguard.evaluate_enhanced(project, @moonmodguard.EnhancedPolicy::default())
println(@moonmodguard.render_full_report(report))

EnhancedPolicy adds CSP-style trust grading (Trusted / Allowed / Blocked), max-dependency limits, and version validation on top of the base policy checks.

Trust Policy Builder

let policy = @moonmodguard.TrustPolicy::new()
  .trust("moonbitlang/")
  .allow("github.com/")
  .block("bad-domain/")
  .default_level(@moonmodguard.Blocked)

let level = policy.check("moonbitlang/x")
// level is Trusted

Batch Audit

let snapshots = [
  @moonmodguard.ProjectSnapshot::{ module_manifest: m1, packages: [] },
  @moonmodguard.ProjectSnapshot::{ module_manifest: m2, packages: [] },
]
let summary = @moonmodguard.batch_audit(snapshots)
println(@moonmodguard.render_batch_summary(summary))

Versioned Dependencies

The parser now supports @version in dependency declarations:

import { "moonbitlang/x@0.4.46" @x }

Use check_version_consistency to validate declared versions, and check_missing_versioned_dep to match module-level versioned deps against package-level imports.

JSON Output

let json = @moonmodguard.render_json(report)
// All string values are properly escaped (quotes, backslashes, newlines, tabs)

SARIF Output (GitHub Code Scanning)

let sarif = @moonmodguard.render_sarif(report, "MoonModGuard")
// Valid SARIF v2.1.0 JSON for GitHub Code Scanning upload

Workspace Scanner

# Recursively audit all packages under a directory
moon run cmd/main -- --workspace .
let pkgs = @moonmodguard.discover_packages(".") raise
let summary = @moonmodguard.audit_workspace(".") raise
println(@moonmodguard.render_batch_summary(summary))

GitHub Annotations

# Output as GitHub Actions workflow commands
moon run cmd/main -- moon.mod --annotations

mooncake.yaml Consistency

let mooncake = match @moonmodguard.parse_mooncake(yaml_text) {
  Ok(m) => m
  Err(_) => abort("parse error")
}
let diags = @moonmodguard.check_mooncake_consistency(mod_manifest, mooncake)
// Reports name/version/license/repository/description/keywords mismatches

Full Audit & Dependency Analysis

full_audit runs the base policy plus every dependency check in one report:

let report = @moonmodguard.full_audit(manifest, packages)
// Combines evaluate_policy with:
//   check_unused_dependency, check_missing_versioned_dep,
//   check_version_consistency, check_version_conflicts,
//   check_self_dependency

Version conflict and self-dependency detection:

// Same source declared with two versions -> "version-conflict"
let conflicts = @moonmodguard.check_version_conflicts(manifest, packages)

// Module imports its own name -> "self-dependency"
let self = @moonmodguard.check_self_dependency(manifest)

Repository URL validation:

@moonmodguard.is_valid_repository_url("https://github.com/a/b") // true
@moonmodguard.is_valid_repository_url("not-a-url")              // false

Public API additions:

  • check_missing_versioned_dep(manifest, packages) -> Array[Diagnostic]
  • check_version_consistency(manifest) -> Array[Diagnostic]
  • check_version_conflicts(manifest, packages) -> Array[Diagnostic]
  • check_self_dependency(manifest) -> Array[Diagnostic]
  • full_audit(manifest, packages) -> AuditReport
  • is_valid_repository_url(repository) -> Bool
  • evaluate_enhanced(project, policy) -> AuditReport
  • render_json(report) -> String
  • render_full_report(report) -> String
  • render_summary(report) -> String
  • batch_audit(snapshots) -> AuditSummary
  • render_batch_summary(summary) -> String
  • TrustPolicy::new() / .trust() / .allow() / .block() / .default_level()
  • EnhancedPolicy::default()

Dependency struct now includes version : String? for versioned dependency declarations.

Design Notes

The parser handles the common MoonBit manifest shape used by package metadata and import declarations. It is not a full MoonBit grammar parser. That boundary is intentional: the first release focuses on release readiness and policy audit checks that can be validated with stable tests.

The default policy accepts Apache-2.0, MIT, and MulanPSL-2.0, and treats moonbitlang/ and wyc060514/ as trusted dependency prefixes. Callers can pass a custom Policy value for stricter project rules.

Competition Materials

  • Proposal source: docs/competition/proposal.md
  • Submission guide: docs/competition/submission-guide.md
  • Acceptance checklist: docs/competition/acceptance-checklist.md
  • Application PDF: docs/competition/MoonModGuard项目申报书.pdf

License

Apache-2.0

关于
1007.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号