framework — guide (About · 🧰 Tools · lifecycle, from the CLI)
Class:
guide· Function axis:framework. What the surfaces do and how to drive them. Shape + rationale:framework-design.md.
modgunn shares the constellation-wide common framework (the same About + Tools + lifecycle every suite app has). Because modgunn is a CLI, the surfaces are four verbs.
About — who is this?
$ modgunn about
Móðguðr — modgunn v0.0.5
the nordisk security + SCIP world-delta gatekeeper (Gjallarbrú)
Guards the bridge: scrutinizes what passes (CVE / license / provenance verdict) …
· Engine A — artifact security VERDICT (scan: multi-ecosystem CVE / license / provenance)
· Engine B — SCIP whole-world dep-tree BEHAVIOUR-DELTA (scip: tripwires / graph-algs / anomaly)
repository: git@codeberg.org:nordisk/modgunn.git
$ modgunn about --json # the stable oracle a robot asserts
{ "name": "modgunn", "display_name": "Móðguðr", "version": "0.0.5", "subtitle": "…gatekeeper…", "engines": [ … ], "framework": [ … ] }
about needs no extra feature — it works in the lean scan build too.
🧰 Tools — one-click demo data through jera
$ modgunn tools # list the menu (needs --features framework)
modgunn 🧰 Tools (jera-backed demo actions):
🩺 Demo advisory feed — generate + scan [starts: modgunn-demo-feed → view: `modgunn warehouse scan`]
Start a pinned demo container (jera) that writes a demo OSV advisory …
$ modgunn tools --json # the roster oracle
# run the demo: start the container (jera) → it writes a demo OSV doc into --out
$ modgunn demo advisory-feed --out ./demo-advisories
demo advisory-feed → jera ContainerSpec: image=docker.io/library/alpine:3.20.3 name=modgunn-demo-feed mount=./demo-advisories:/out
(plan only) rebuild with `--features framework-oci` to start the container live; then `modgunn warehouse import --osv ./demo-advisories`
Building with --features framework-oci makes demo advisory-feed actually start the container (routed THROUGH draupnir's ONE OCI engine, as a tracked jera job) and write the demo OSV file. Then fold + view it:
$ modgunn warehouse import --warehouse /wh --rev demo --osv ./demo-advisories
$ modgunn warehouse scan --warehouse /wh
In Rust (consuming the same seam):
let spec = modgunn::tools::demo_feed_spec("./demo-advisories"); // a jera ContainerSpec
# #[cfg(feature = "framework-oci")]
let outcome = modgunn::tools::run_demo_feed("./demo-advisories")?; // run THROUGH jera as a job
Service lifecycle — through the ship (skidbladnir)
modgunn declares its world-delta service through the SHARED ship, not a hand-written unit:
$ modgunn service --unit
[Unit]
Description=Móðguðr — the nordisk security + SCIP world-delta gatekeeper
…
[Service]
User=modgunn # its OWN dedicated system user (L5)
Environment=MODGUNN_WORLDDELTA_ADDR=127.0.0.1:50071
ExecStart=/usr/local/bin/modgunn world-delta watch
Restart=on-failure
…
$ modgunn service --json # unit · user · port · fat/thin posture
$ modgunn service --unit --user-scope # a `systemctl --user` dev unit (runs as YOU, no User=)
The dedicated modgunn user is provisioned at install time via skidbladnir::systemd::ensure_system_user("modgunn", …) — the SAME code nornir→nornir, holger→holger use. (The watcher daemon the unit runs is future work.)
Feature matrix — what to compile in
| you want | build with |
about only (lean) |
default (scan) — nothing extra |
tools / demo plan + service --unit |
--features framework |
| the demo container to actually run | --features framework-oci |
| the binary (all verbs) | --features "warehouse framework" |
Build atoms — kind × linkage (cargo xtask build)
The feature flags above are the raw cargo axis; the named builds modgunn ships are declared once as data in build-variants.toml and resolved by the ONE build verb, cargo xtask build (nornir-build-thing's suite_cli). ONE atom, and it is a row of the constellation build matrix:
| suite | atom | role | linkage | bin |
ORIGINAL |
modgunn ⭐ |
client | fat | modgunn |
The CLI: Engine A+B + the skade warehouse seam compiled IN (warehouse = ["dep:skade", …]), so it works with no server running — which is what the matrix means by a fat client. A batch CLI that does one job and exits.
$ cargo xtask build --suite ORIGINAL # every cargo atom of the delivery
$ cargo xtask build --suite ORIGINAL --atom modgunn # cargo build -p modgunn --bin modgunn --features scan,scip,warehouse,rustsec,provenance-verify --no-default-features --profile release
$ cargo xtask build --suite ORIGINAL --list # resolve and print; build nothing
$ dwarves buildthing modgunn --suite ORIGINAL # the same resolver, from outside the repo
modgunn is NOT a server, has no wire and has no UI. The matrix gives every member five shapes (<x>-server · <x> · <x>-cli · <x>-ui · <x>-solo); modgunn fills exactly ONE, and the other four are declared GAPS rather than phantom atoms — because carrying the suites tag is what claims Build-Thing status, and an atom that claims it while building nothing is a promise the repo cannot keep. The service --unit verb above renders a systemd unit; it does not start one, the module behind it is not even compiled into the shipped modgunn atom, and the unit's ExecStart names modgunn world-delta watch, a verb the CLI does not have. Full measurements: suite-atoms-design.md.
The asymmetry guard. modgunn is the cycle-breaker holger + nornir both depend on, so they are upstream: a fat variant may embed only skade (downstream). A variant that tried embeds = ["nornir"] is rejected by BuildVariantSet::validate.