commissioning: the layer, the acceptance tests, the harness rule, the docs, and the bench drills

meta-forgefirm: the forgefirm-users init replays the account at boot;
sshd refuses root and empty passwords and runs only while the panel
turns it on; the release image keeps an empty root password for the
console; the console banner; avahi announces forgefirm.local; https in
libmicrohttpd and ulfius; the panel on 80 and 443; the license bundle on
the rootfs; release.sh checks the root policy on the built rootfs.

forgetest: the commission suites (commission, commission_dark,
commission_sheet: 23 cases); the runner turns cloud mode on with the
typed phrase for a test that declares it; the baseline's motor_lock is
0; the log-export test checks the bundle for the camera key; the record
helpers write bytes as given and join the daemon's paths as POSIX. The
stream harness gains rule 24: a hold verdict is held again after a
resume. Bench drills: lens_travel.py and lens_stop_accel.py.

Docs: BRINGUP carries the present state; CAMPAIGN-LOG carries the dated
record.
This commit is contained in:
ScottW514
2026-09-06 19:56:05 -04:00
parent ff9796cde6
commit 97287aa6a9
59 changed files with 15113 additions and 9139 deletions
@@ -0,0 +1,12 @@
#!/bin/sh
# udhcpc hook: /usr/share/udhcpc/default.script runs every file in
# /etc/udhcpc.d with the lease event as $1; 50default applies the lease
# first. Refresh the address block of the console banner on every event.
case "$1" in
bound|renew|deconfig|leasefail|nak)
/usr/sbin/forgefirm-banner
;;
esac
exit 0
@@ -0,0 +1,63 @@
#!/bin/sh
# Rewrites the address block of /etc/issue, the serial-console login
# banner: the control panel by mDNS name, then one https:// URL per
# global address of wlan0 (and eth0 when the machine has one). Every
# other line of /etc/issue stays as the image build wrote it. The block
# sits between the marker lines "# ForgeFIRM addresses" and "# end" and
# is appended when absent. Called by the init script at boot and by the
# udhcpc hook on every lease event. Idempotent: the file is written only
# when the block changes.
PATH=/sbin:/usr/sbin:/bin:/usr/bin
ISSUE=/etc/issue
MARK_BEGIN='# ForgeFIRM addresses'
MARK_END='# end'
PANEL='Control panel: https://forgefirm.local/'
# One URL per global address; an IPv6 address gets its URL brackets.
# Tentative, deprecated and temporary addresses are left out.
addresses () {
command -v ip >/dev/null 2>&1 || return 0
for dev in wlan0 eth0; do
[ -d "/sys/class/net/$dev" ] || continue
ip addr show dev "$dev" 2>/dev/null | awk '
($1 == "inet" || $1 == "inet6") && / scope global/ \
&& !/tentative/ && !/deprecated/ && !/temporary/ {
a = $2
sub(/\/.*/, "", a)
if ($1 == "inet6") a = "[" a "]"
print "https://" a "/"
}'
done
}
block () {
echo "$MARK_BEGIN"
echo "$PANEL"
addrs=$(addresses)
if [ -n "$addrs" ]; then
echo "$addrs"
else
echo "no network address yet"
fi
echo "$MARK_END"
}
[ -f "$ISSUE" ] || exit 0
new=$(block)
old=$(awk -v b="$MARK_BEGIN" -v e="$MARK_END" \
'$0 == b { p = 1 } p { print } $0 == e { p = 0 }' "$ISSUE")
[ "$new" = "$old" ] && exit 0
tmp="$ISSUE.tmp.$$"
awk -v b="$MARK_BEGIN" -v e="$MARK_END" -v blk="$new" '
$0 == b { print blk; seen = 1; skip = 1; next }
$0 == e && skip { skip = 0; next }
!skip { print }
END { if (!seen) print blk }
' "$ISSUE" > "$tmp" || { rm -f "$tmp"; exit 1; }
chmod 0644 "$tmp"
mv -f "$tmp" "$ISSUE"
exit 0
@@ -0,0 +1,26 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: forgefirm-banner
# Required-Start: $network
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: ForgeFIRM console banner: control panel addresses
### END INIT INFO
# Writes the address block of /etc/issue once at boot; the udhcpc hook
# (/etc/udhcpc.d/60forgefirm-banner) keeps it current afterward.
case "$1" in
start|restart|reload|force-reload)
/usr/sbin/forgefirm-banner
;;
stop)
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0
@@ -0,0 +1,30 @@
SUMMARY = "ForgeFIRM console banner: the control panel addresses in /etc/issue"
DESCRIPTION = "Keeps an address block in the serial-console login banner \
(/etc/issue): the control panel by mDNS name and by every global address \
of wlan0 and eth0. Refreshed at boot and on every DHCP lease event."
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = " \
file://forgefirm-banner \
file://forgefirm-banner.init \
file://60forgefirm-banner \
"
S = "${WORKDIR}"
inherit update-rc.d
INITSCRIPT_NAME = "forgefirm-banner"
# 99: after networking (S01); an address the lease brings later arrives
# through the udhcpc hook.
INITSCRIPT_PARAMS = "start 99 2 3 4 5 ."
do_install() {
install -Dm 0755 ${WORKDIR}/forgefirm-banner ${D}${sbindir}/forgefirm-banner
install -Dm 0755 ${WORKDIR}/forgefirm-banner.init ${D}${sysconfdir}/init.d/forgefirm-banner
# busybox udhcpc runs /etc/udhcpc.d/* (run-parts) on every lease event
install -Dm 0755 ${WORKDIR}/60forgefirm-banner ${D}${sysconfdir}/udhcpc.d/60forgefirm-banner
}
FILES:${PN} += "${sysconfdir}/udhcpc.d"