Move the console onto ReUI PRO
Install ReUI (MCP, skill, @reui registry, Tailwind v4, shadcn base-nova) and move the shared UI onto it: Button, Tag, Check, Input/Textarea, Segmented, Alert, Panel, Dialog, Tooltip, Menu and Select (Popover), Toast (sonner), the Table frame (DataGrid), the Dashboard KPI strip, the shnt Ops palette, Geist and the type scale. Design only: behaviour, texts and roles are unchanged. Tests that asserted the old DOM were updated; the tests now format numbers in English wherever they run. docs/reui-migration-plan.md records the plan and its decisions. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
f3531c64f9
680 files changed
+139836
No files matched your search
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env bash
|
||||
# Side-by-side comparison by ACTION, not by bytes of the page.
|
||||
#
|
||||
# The project's governing constraint is "design only, zero functionality", and
|
||||
# that enables the check that actually counts: run the same action on both
|
||||
# instances and verify the RESULTING SERVER STATE is the same. If the body the
|
||||
# new console sends differs by one parameter, the record left behind differs and
|
||||
# it shows up here.
|
||||
#
|
||||
# The bodies are the ones upstream builds, copied from its JS. The new console
|
||||
# sends the same ones: that is what is being verified.
|
||||
#
|
||||
# Usage: ./check-parity-actions.sh
|
||||
set -uo pipefail
|
||||
|
||||
DEV=http://127.0.0.1:5380
|
||||
REF=http://127.0.0.1:5381
|
||||
USERNAME=admin
|
||||
PASSWORD=technitium-ui-dev
|
||||
ZONE=paridad.test
|
||||
|
||||
failures=0
|
||||
|
||||
token() {
|
||||
curl -s "$1/api/user/login?user=$USERNAME&pass=$PASSWORD&includeInfo=false" |
|
||||
python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])'
|
||||
}
|
||||
|
||||
TD=$(token "$DEV")
|
||||
TR=$(token "$REF")
|
||||
|
||||
# Leaves the zone identical on both before each comparison block.
|
||||
reset_zone() {
|
||||
for pair in "$DEV $TD" "$REF $TR"; do
|
||||
set -- $pair
|
||||
curl -s "$1/api/zones/delete?token=$2&zone=$ZONE" >/dev/null
|
||||
curl -s "$1/api/zones/create?token=$2&zone=$ZONE&type=Primary" >/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
# What is compared: the zone's records, minus whatever changes with the
|
||||
# environment.
|
||||
#
|
||||
# Three things are normalised, all three for the same reason: they are not parity.
|
||||
# · `lastModified` and the SOA serial change with the clock.
|
||||
# · The SERVER NAME is embedded in the NS and the SOA of every zone, and the
|
||||
# two containers deliberately have a different `DNS_SERVER_DOMAIN`
|
||||
# (dev.technitium-ui.test / ref.technitium-ui.test). Without substituting it,
|
||||
# all fourteen comparisons come out different over the hostname and not over
|
||||
# the action.
|
||||
fingerprint() {
|
||||
curl -s "$1/api/zones/records/get?token=$2&domain=$ZONE&zone=$ZONE&listZone=true" |
|
||||
python3 -c '
|
||||
import sys, json, re
|
||||
d = json.load(sys.stdin)["response"]
|
||||
out = []
|
||||
for r in sorted(d["records"], key=lambda x: (x["type"], x["name"])):
|
||||
r.pop("lastModified", None)
|
||||
if r["type"] == "SOA":
|
||||
r["rData"].pop("serial", None)
|
||||
out.append(r)
|
||||
text = json.dumps(out, sort_keys=True)
|
||||
print(re.sub(r"(dev|ref)\.technitium-ui\.test", "THIS-SERVER", text))'
|
||||
}
|
||||
|
||||
# compare <name> <body-or-query> [method]
|
||||
compare() {
|
||||
local name=$1 path=$2 body=${3:-} method=${4:-GET}
|
||||
|
||||
for pair in "$DEV $TD" "$REF $TR"; do
|
||||
set -- $pair
|
||||
if [ "$method" = POST ]; then
|
||||
curl -s -X POST "$1/api/$path?token=$2&node=" --data "$body" >/dev/null
|
||||
else
|
||||
curl -s "$1/api/$path?token=$2&$body" >/dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
local d r
|
||||
d=$(fingerprint "$DEV" "$TD")
|
||||
r=$(fingerprint "$REF" "$TR")
|
||||
|
||||
if [ "$d" = "$r" ]; then
|
||||
echo " OK $name"
|
||||
else
|
||||
echo " DIFFERENT $name"
|
||||
diff <(echo "$r" | python3 -m json.tool) <(echo "$d" | python3 -m json.tool) | head -20
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "== record creates =="
|
||||
reset_zone
|
||||
compare "A with PTR" "zones/records/add" \
|
||||
"zone=$ZONE&domain=www.$ZONE&type=A&ttl=3600&overwrite=false&comments=&expiryTtl=&ipAddress=10.0.0.1&ptr=false&createPtrZone=false&updateSvcbHints=false" POST
|
||||
compare "MX" "zones/records/add" \
|
||||
"zone=$ZONE&domain=$ZONE&type=MX&ttl=3600&overwrite=false&comments=&expiryTtl=&preference=10&exchange=mail.$ZONE" POST
|
||||
compare "split TXT" "zones/records/add" \
|
||||
"zone=$ZONE&domain=$ZONE&type=TXT&ttl=3600&overwrite=false&comments=note&expiryTtl=&text=v=spf1 -all&splitText=true" POST
|
||||
compare "SRV" "zones/records/add" \
|
||||
"zone=$ZONE&domain=_s._tcp.$ZONE&type=SRV&ttl=3600&overwrite=false&comments=&expiryTtl=&priority=1&weight=2&port=443&target=www.$ZONE" POST
|
||||
compare "CAA with default values" "zones/records/add" \
|
||||
"zone=$ZONE&domain=$ZONE&type=CAA&ttl=3600&overwrite=false&comments=&expiryTtl=&flags=0&tag=issue&value=letsencrypt.org" POST
|
||||
compare "SVCB with params and automatic hint" "zones/records/add" \
|
||||
"zone=$ZONE&domain=svc.$ZONE&type=SVCB&ttl=3600&overwrite=false&comments=&expiryTtl=&svcPriority=1&svcTargetName=www.$ZONE&svcParams=alpn|h2&autoIpv4Hint=true&autoIpv6Hint=false" POST
|
||||
compare "CNAME" "zones/records/add" \
|
||||
"zone=$ZONE&domain=alias.$ZONE&type=CNAME&ttl=3600&overwrite=false&comments=&expiryTtl=&cname=www.$ZONE" POST
|
||||
|
||||
echo "== edits =="
|
||||
compare "edit the A: old and new" "zones/records/update" \
|
||||
"zone=$ZONE&type=A&domain=www.$ZONE&newDomain=www.$ZONE&ttl=1800&disable=false&comments=&expiryTtl=&ipAddress=10.0.0.1&newIpAddress=10.0.0.2&ptr=false&createPtrZone=false&updateSvcbHints=false" POST
|
||||
compare "disable the MX by resending it whole" "zones/records/update" \
|
||||
"zone=$ZONE&type=MX&domain=$ZONE&ttl=3600&disable=true&comments=&expiryTtl=&preference=10&exchange=mail.$ZONE" POST
|
||||
compare "edit the SOA" "zones/records/update" \
|
||||
"zone=$ZONE&type=SOA&domain=$ZONE&newDomain=$ZONE&ttl=900&disable=false&comments=&expiryTtl=&primaryNameServer=ns1.$ZONE&responsiblePerson=hostadmin@$ZONE&serial=42&refresh=900&retry=300&expire=604800&minimum=900&useSerialDateScheme=false" POST
|
||||
|
||||
echo "== deletes =="
|
||||
compare "delete the CNAME (no parameters: falls to default)" "zones/records/delete" \
|
||||
"zone=$ZONE&domain=alias.$ZONE&type=CNAME" POST
|
||||
compare "delete the SVCB by its flattened svcParams" "zones/records/delete" \
|
||||
"zone=$ZONE&domain=svc.$ZONE&type=SVCB&svcPriority=1&svcTargetName=www.$ZONE&svcParams=alpn|h2" POST
|
||||
compare "delete the SRV by its four fields" "zones/records/delete" \
|
||||
"zone=$ZONE&domain=_s._tcp.$ZONE&type=SRV&priority=1&weight=2&port=443&target=www.$ZONE" POST
|
||||
|
||||
echo "== zone options =="
|
||||
compare "options/set with the empty lists as \"false\"" "zones/options/set" \
|
||||
"zone=$ZONE&catalog=&overrideCatalogQueryAccess=false&overrideCatalogZoneTransfer=false&overrideCatalogNotify=false&primaryNameServerAddresses=&primaryZoneTransferProtocol=Tcp&primaryZoneTransferTsigKeyName=&validateZone=false&queryAccess=Allow&queryAccessNetworkACL=&zoneTransfer=AllowOnlyZoneNameServers&zoneTransferNetworkACL=false&zoneTransferTsigKeyNames=false¬ify=ZoneNameServers¬ifyNameServers=false¬ifySecondaryCatalogsNameServers=false&update=Deny&updateNetworkACL=false&updateSecurityPolicies=false"
|
||||
|
||||
echo
|
||||
if [ "$failures" -eq 0 ]; then
|
||||
echo "PARITY: every action leaves the same state"
|
||||
exit 0
|
||||
fi
|
||||
echo "PARITY: $failures actions diverge"
|
||||
exit 2
|
||||
Reference in new issue
Block a user