cli

package
v0.11.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

Deploy-repo scaffold + creation (mallcoppro-f3b): `mallcop init --create-repo owner/name` turns the plain local scaffold runInit already writes (mallcop.yaml, store/, events.jsonl) into a customer DEPLOYMENT repo pushed to a real GitHub repository, so the customer never compiles mallcop locally — a scheduled GitHub Action does.

Rulings this file implements:

  • D1 THIN-EMBED: the repo pins mallcop via go.mod (require github.com/mallcop-app/mallcop <version>) so a customer authoring a detectors/<name> sidecar gets the real core/detect + pkg/detectorhost types from the published module — never a fork, never vendored source.
  • D2+2fd WASM SIDECARS: the scaffolded CI workflow builds each detectors/<name> to wasip1 .wasm into detectors/bin/ (matching cfg.Detectors.Sidecars.Dir's default — see resolveSidecarsDir in sidecars.go). It NEVER rebuilds the whole mallcop binary from customer code — the core binary is always the pinned prebuilt release tarball downloaded from GitHub Releases.
  • D3 SAME-REPO: findings live in store/ inside the SAME GitHub repo, not a separate one. store/ is (per core/store's own design — see openOrInitStore in scan.go) its own nested git repository, so it can't ride along on the deployment repo's main branch across ephemeral Actions runs. The scaffolded workflow instead backs store/ with a dedicated branch (mallcopFindingsBranch) of the SAME repo: restore it before the scan, push it back after. Main branch's .gitignore excludes store/ so an operator's ordinary "git add -A" on main can never swallow findings history into the wrong branch.

GitHub App authorize seam (explicit, NOT exercised by this item's live proof): mallcop-pro already holds the GitHub App private key server-side and exposes POST /v1/github/token (see mallcop-pro/internal/server/github_token.go) to exchange a customer's donut-rail API key + their App installation_id for a scoped installation access token. proAppToken below implements that exact exchange and is unit tested against an httptest stand-in of the endpoint. It is not exercised against the live api.mallcop.app here — that needs a funded customer account and a real App installation, which is out of scope for the smallest honest v1 (see the item's DISCOVER FIRST note). The transport actually exercised live is envGitHubToken: a raw token from an environment variable (e.g. `gh auth token`'s output), used as a personal access token would be.

Package cli implements the full mallcop CLI as an importable package. An external module can embed the entire CLI with:

import "github.com/mallcop-app/mallcop/cli"
func main() { cli.Main() }

The embedder controls its own detector linkage the same way cmd/mallcop does: blank-import whatever detect.Register-ing package(s) it wants before calling cli.Main() (core/detect/authored, or an external equivalent). This package intentionally does NOT import core/detect/authored itself — that blank import is the human-wired registration seam and belongs to the binary's main package, not to this reusable library.

Usage:

mallcop scan        [--config <mallcop.yaml>] | --store <dir> [--events <file> | --connector github --github-org <org>] [--tuning <yaml>] [--json]
mallcop detect      [--baseline <path>] [--tuning <yaml>]   < events.jsonl   > findings.jsonl
mallcop exam-detect [--json] [--tuning <yaml>]
mallcop validate-proposal --base <ref> [--head <ref>] [--guard-only] [--allow-no-coverage-gain] [--json]
mallcop collect     --store <dir> [--fidelity <json>] [--json]
mallcop init        [--dir <path>] [--pro] [--create-repo owner/name] [--mallcop-version <tag>] [--github-token-env <VAR>]
mallcop migrate     [--dir <path>] [--mallcop-version <tag>] [--config-only] [--dry-run]
mallcop status      --store <dir>
mallcop config
mallcop config set connector --kind=file|github|cloud --id=<id> [...]
mallcop config set autonomy <non|semi|fully>
mallcop feedback    <finding_id> approve|dismiss --store <dir> [--reason <text>] [--by <name>]
mallcop investigate --question <text> --store <dir> [--baseline <path>] | --serve --inbox <file> --outbox <file> --store <dir>

In-place deploy-repo upgrade (mallcoppro-973): `mallcop migrate` re-rigs an EXISTING customer deployment repo to the current schema + pinned release, so a live customer can bump versions without a hand re-scaffold.

The v0.10.0 config loader (core/config) is a STRICT decoder: an old-shape mallcop.yaml (v0.9.3 and earlier — `secrets:`/`routing:`/`actor_chain:`/ `pro:` blocks, `connectors:` as a kind->cfg MAP) is a loud load error, so every pre-v0.10 deploy repo's workflows fail the moment they read the config ("field secrets not found", "connectors: cannot unmarshal map into []Connector", "field routing not found"). This command performs the exact re-rig reproduced against the customer0 fixture:

  1. mallcop.yaml — legacy shape -> the new strict schema (config.Config), carrying over what maps (github org, findings budget, the donut rail) and LOUDLY reporting every dropped key rather than silently eating it.
  2. .github/workflows/ — force-refresh scan.yml AND add the (v0.10) new mallcop-investigate.yml, both pinned to the target release.
  3. go.mod — bump the github.com/mallcop-app/mallcop require to the target release so CI sidecar builds match the workflow's downloaded binary.

It is offline and in-place: it rewrites files under --dir (a checked-out deploy repo). Committing + pushing the result is the operator's step (the printed next-steps), the same division of labor as `mallcop init` vs `mallcop init --create-repo`. Setting the MALLCOP_API_KEY repo secret is likewise printed as the exact `gh secret set` command (mallcoppro-7b1's live GitHub-secret-API path is deferred — see the item).

Index

Constants

View Source
const CollectSchemaVersion = 1

CollectSchemaVersion is the collect-envelope wire-format version. It is the STABLE PROCESS BOUNDARY between mallcop (this repo) and the mallcop-pro proposer: mallcop-pro must NOT import mallcop (separate Go modules), so it consumes the collectors as JSON over `mallcop collect --json` and duplicates the MappingGap / GapCandidate structs on its side. Bump this on any backwards-incompatible change to the envelope shape, exactly as selfgate.GateSchemaVersion versions the validate-proposal wire format.

Variables

This section is empty.

Functions

func Main

func Main()

Main is the CLI entrypoint. It parses os.Args (via the flag package's default CommandLine), dispatches to the requested subcommand, and calls os.Exit with the same exit codes cmd/mallcop has always used:

0  success
1  findings detected (scan / detect / exam-detect / validate-proposal)
2  any other command failure

Callers (cmd/mallcop's main.go, or an external embedder) are expected to blank-import their detector registration package(s) before calling Main, then simply call cli.Main() as their entire main().

Types

type ScanSummary

type ScanSummary struct {
	EventsScanned    int `json:"events_scanned"`
	FindingsDetected int `json:"findings_detected"`
	Escalated        int `json:"escalated"`
	Resolved         int `json:"resolved"`
}

ScanSummary holds the results of a completed scan cycle.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL