From 6c2d03b6e137fb55c95f6f3fa9513f640a1dded2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Fri, 14 Aug 2026 23:21:20 -0700 Subject: [PATCH 1/5] chore: stop tracking stray files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit netplanStatus.txt is `netplan status` output redirected to a file and committed. It contains this machine's MAC addresses, a routable global IPv6 address, LAN subnets, and the local k3s, flannel, CNI, and LXD bridge topology. .just/remote/react.mod.just is a fetched copy of a shared justfile. The justfiles specification says fetched files are excluded from version control, and every other repository ignores .just/ entirely. This one committed the file before the ignore rule existed, so the rule never applied — gitignore only suppresses untracked files. Broaden the ignore from .just/remote/* to .just/, and add netplanStatus.txt so a stray redirect does not land again. This removes both from the working tree, not from history. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude Opus 5 (1M context) --- .gitignore | 3 ++- .just/remote/react.mod.just | 4 ---- netplanStatus.txt | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 .just/remote/react.mod.just delete mode 100644 netplanStatus.txt diff --git a/.gitignore b/.gitignore index 989e65452..92ebca194 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,10 @@ configs/osapi.*.yaml database.db* dist/ docs/node_modules/ -.just/remote/* +.just/ .nats/jetstream/ pki/ +netplanStatus.txt result.xml test/vendor/ tmp/ diff --git a/.just/remote/react.mod.just b/.just/remote/react.mod.just deleted file mode 100644 index 02b64b06f..000000000 --- a/.just/remote/react.mod.just +++ /dev/null @@ -1,4 +0,0 @@ -# Local override: run react recipes in the ui/ directory. -set working-directory := '../../ui' - -import? 'react.just' diff --git a/netplanStatus.txt b/netplanStatus.txt deleted file mode 100644 index d13db0f3b..000000000 --- a/netplanStatus.txt +++ /dev/null @@ -1 +0,0 @@ -{"netplan-global-state": {"online": true, "nameservers": {"addresses": ["127.0.0.53"], "search": ["."], "mode": "stub"}}, "lo": {"index": 1, "adminstate": "UP", "operstate": "UNKNOWN", "type": "ethernet", "macaddress": "00:00:00:00:00:00", "addresses": [{"127.0.0.1": {"prefix": 8}}, {"::1": {"prefix": 128}}], "routes": [{"to": "127.0.0.0/8", "family": 2, "from": "127.0.0.1", "type": "local", "scope": "host", "protocol": "kernel", "table": "local"}, {"to": "127.0.0.1", "family": 2, "from": "127.0.0.1", "type": "local", "scope": "host", "protocol": "kernel", "table": "local"}, {"to": "127.255.255.255", "family": 2, "from": "127.0.0.1", "type": "broadcast", "scope": "link", "protocol": "kernel", "table": "local"}, {"to": "::1", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}]}, "wlp0s20f3": {"index": 3, "adminstate": "UP", "operstate": "UP", "type": "wifi", "backend": "networkd", "id": "wlp0s20f3", "macaddress": "b0:a4:60:17:cb:90", "vendor": "Intel Corporation", "addresses": [{"192.168.0.241": {"prefix": 16, "flags": ["dhcp"]}}, {"2600:6c50:4900:c740:b2a4:60ff:fe17:cb90": {"prefix": 64}}, {"fdd6:733a:3f9:1:b2a4:60ff:fe17:cb90": {"prefix": 64}}, {"fe80::b2a4:60ff:fe17:cb90": {"prefix": 64, "flags": ["link"]}}], "dns_addresses": ["192.168.0.247", "2001:1998:f00:1::1", "2001:1998:f00:3::1", "2001:1998:f00:2::1"], "routes": [{"to": "default", "family": 2, "via": "192.168.0.1", "from": "192.168.0.241", "metric": 600, "type": "unicast", "scope": "global", "protocol": "dhcp", "table": "main"}, {"to": "192.168.0.0/16", "family": 2, "from": "192.168.0.241", "metric": 600, "type": "unicast", "scope": "link", "protocol": "kernel", "table": "main"}, {"to": "192.168.0.1", "family": 2, "from": "192.168.0.241", "metric": 600, "type": "unicast", "scope": "link", "protocol": "dhcp", "table": "main"}, {"to": "192.168.0.247", "family": 2, "from": "192.168.0.241", "metric": 600, "type": "unicast", "scope": "link", "protocol": "dhcp", "table": "main"}, {"to": "192.168.0.241", "family": 2, "from": "192.168.0.241", "type": "local", "scope": "host", "protocol": "kernel", "table": "local"}, {"to": "192.168.255.255", "family": 2, "from": "192.168.0.241", "type": "broadcast", "scope": "link", "protocol": "kernel", "table": "local"}, {"to": "2600:6c50:4900:c740::/64", "family": 10, "metric": 600, "type": "unicast", "scope": "global", "protocol": "ra", "table": "main"}, {"to": "fd56:aa96:7e46::/64", "family": 10, "via": "fe80::1c2d:b4a4:4f6f:85a", "metric": 600, "type": "unicast", "scope": "global", "protocol": "ra", "table": "main"}, {"to": "fdd6:733a:3f9:1::/64", "family": 10, "metric": 600, "type": "unicast", "scope": "global", "protocol": "ra", "table": "main"}, {"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "default", "family": 10, "via": "fe80::1a90:88ff:fe6b:f272", "metric": 600, "type": "unicast", "scope": "global", "protocol": "ra", "table": "main"}, {"to": "2600:6c50:4900:c740::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "2600:6c50:4900:c740:b2a4:60ff:fe17:cb90", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fdd6:733a:3f9:1::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fdd6:733a:3f9:1:b2a4:60ff:fe17:cb90", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::b2a4:60ff:fe17:cb90", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}]}, "flannel.1": {"index": 4, "adminstate": "UP", "operstate": "UNKNOWN", "type": "tunnel", "tunnel_mode": "vxlan", "macaddress": "5a:46:ac:96:96:1c", "addresses": [{"10.42.0.0": {"prefix": 32}}, {"fe80::5846:acff:fe96:961c": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "10.42.0.0", "family": 2, "from": "10.42.0.0", "type": "local", "scope": "host", "protocol": "kernel", "table": "local"}, {"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::5846:acff:fe96:961c", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}]}, "cni0": {"index": 5, "adminstate": "UP", "operstate": "UP", "type": "bridge", "macaddress": "06:12:3b:bd:0e:d9", "addresses": [{"10.42.0.1": {"prefix": 24}}, {"fe80::4c5f:e5ff:fe41:e658": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "10.42.0.0/24", "family": 2, "from": "10.42.0.1", "type": "unicast", "scope": "link", "protocol": "kernel", "table": "main"}, {"to": "10.42.0.1", "family": 2, "from": "10.42.0.1", "type": "local", "scope": "host", "protocol": "kernel", "table": "local"}, {"to": "10.42.0.255", "family": 2, "from": "10.42.0.1", "type": "broadcast", "scope": "link", "protocol": "kernel", "table": "local"}, {"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::4c5f:e5ff:fe41:e658", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "interfaces": ["veth38cc21af", "vethaab83896", "vethab727056", "veth9109f820", "vethddba31e1", "veth9c33a87b", "veth4b36aba2", "vethb103745e", "veth319c9203", "veth0ad2b054"]}, "veth38cc21af": {"index": 6, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "8a:14:6b:33:c7:5c", "addresses": [{"fe80::8814:6bff:fe33:c75c": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::8814:6bff:fe33:c75c", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "vethaab83896": {"index": 7, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "2e:79:14:b6:69:d9", "addresses": [{"fe80::2c79:14ff:feb6:69d9": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::2c79:14ff:feb6:69d9", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "vethab727056": {"index": 8, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "6a:61:f5:39:fd:79", "addresses": [{"fe80::6861:f5ff:fe39:fd79": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::6861:f5ff:fe39:fd79", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "veth9109f820": {"index": 9, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "56:5b:2b:dd:82:18", "addresses": [{"fe80::545b:2bff:fedd:8218": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::545b:2bff:fedd:8218", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "vethddba31e1": {"index": 10, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "16:cb:e7:7d:e8:ff", "addresses": [{"fe80::14cb:e7ff:fe7d:e8ff": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::14cb:e7ff:fe7d:e8ff", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "veth9c33a87b": {"index": 11, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "f2:dc:88:d3:d3:95", "addresses": [{"fe80::f0dc:88ff:fed3:d395": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::f0dc:88ff:fed3:d395", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "veth4b36aba2": {"index": 12, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "66:aa:63:0f:3d:4d", "addresses": [{"fe80::64aa:63ff:fe0f:3d4d": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::64aa:63ff:fe0f:3d4d", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "vethb103745e": {"index": 13, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "0a:9b:c3:1d:11:7a", "addresses": [{"fe80::89b:c3ff:fe1d:117a": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::89b:c3ff:fe1d:117a", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "veth319c9203": {"index": 14, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "5a:ae:b0:ae:24:6b", "addresses": [{"fe80::58ae:b0ff:feae:246b": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::58ae:b0ff:feae:246b", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "veth0ad2b054": {"index": 15, "adminstate": "UP", "operstate": "UP", "type": "virtual-ethernet", "macaddress": "ee:9a:08:43:14:ca", "addresses": [{"fe80::ec9a:8ff:fe43:14ca": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::ec9a:8ff:fe43:14ca", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "bridge": "cni0"}, "lxdbr0": {"index": 16, "adminstate": "UP", "operstate": "UP", "type": "bridge", "macaddress": "00:16:3e:f8:f4:f3", "addresses": [{"10.95.130.1": {"prefix": 24}}, {"fd42:94ae:4418:e857::1": {"prefix": 64}}, {"fe80::216:3eff:fef8:f4f3": {"prefix": 64, "flags": ["link"]}}], "routes": [{"to": "10.95.130.0/24", "family": 2, "from": "10.95.130.1", "type": "unicast", "scope": "link", "protocol": "kernel", "table": "main"}, {"to": "10.95.130.1", "family": 2, "from": "10.95.130.1", "type": "local", "scope": "host", "protocol": "kernel", "table": "local"}, {"to": "10.95.130.255", "family": 2, "from": "10.95.130.1", "type": "broadcast", "scope": "link", "protocol": "kernel", "table": "local"}, {"to": "fd42:94ae:4418:e857::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fe80::/64", "family": 10, "metric": 256, "type": "unicast", "scope": "global", "protocol": "kernel", "table": "main"}, {"to": "fd42:94ae:4418:e857::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fd42:94ae:4418:e857::1", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::", "family": 10, "type": "anycast", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "fe80::216:3eff:fef8:f4f3", "family": 10, "type": "local", "scope": "global", "protocol": "kernel", "table": "local"}, {"to": "ff00::/8", "family": 10, "metric": 256, "type": "multicast", "scope": "global", "protocol": "kernel", "table": "local"}], "interfaces": ["tapbd419562"]}, "tapbd419562": {"index": 17, "adminstate": "UP", "operstate": "UP", "type": "tunnel", "tunnel_mode": "tun", "macaddress": "1e:ce:32:d6:c8:b9", "bridge": "lxdbr0"}} From d1b799111ef51b24cea28d32f3244894d76ace23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sat, 15 Aug 2026 09:37:25 -0700 Subject: [PATCH 2/5] fix: fetch react.mod.just Untracking .just/remote/react.mod.just broke the build: fetch retrieved react.just but never react.mod.just, which is why that file was committed in the first place. Adds the missing curl so the module is provisioned like every other one, rather than depending on a copy in git. Co-Authored-By: Claude Opus 5 (1M context) --- justfile | 1 + 1 file changed, 1 insertion(+) diff --git a/justfile b/justfile index 06c6dbcf2..a3b7fce60 100644 --- a/justfile +++ b/justfile @@ -21,6 +21,7 @@ fetch: curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/just.just -o .just/remote/just.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.mod.just -o .just/remote/docker.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.just -o .just/remote/docker.just + curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.mod.just -o .just/remote/react.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.just -o .just/remote/react.just # --- Top-level orchestration --- From d4dcec8be4b271374214061b15bc789f4f05a81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sat, 15 Aug 2026 09:38:56 -0700 Subject: [PATCH 3/5] fix: keep the react module's local override tracked Untracking .just/remote/react.mod.just was wrong. The file is a deliberate override, and says so: upstream sets working-directory to the repository root, but osapi's React app lives in ui/, so the local copy points at ../../ui. Fetching upstream's copy instead broke `just react::deps` -- bun looked for package.json at the repository root, where there is none. Restores the file and narrows .gitignore to ignore fetched modules except this one, so the exception is visible rather than implied. netplanStatus.txt, which is host data nothing reads, stays removed. Co-Authored-By: Claude Opus 5 (1M context) --- .gitignore | 8 ++++++-- .just/remote/react.mod.just | 4 ++++ justfile | 1 - 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 .just/remote/react.mod.just diff --git a/.gitignore b/.gitignore index 92ebca194..ca07c6e28 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,9 @@ configs/osapi.*.yaml database.db* dist/ docs/node_modules/ -.just/ +.just/remote/* .nats/jetstream/ pki/ -netplanStatus.txt result.xml test/vendor/ tmp/ @@ -26,3 +25,8 @@ examples/** !examples/**/*.go !examples/**/*.mod !examples/**/*.sum + +# Fetched justfile modules, except osapi's local react override +# (upstream sets working-directory to the repo root; osapi's React app is in ui/) +.just/remote/* +!.just/remote/react.mod.just diff --git a/.just/remote/react.mod.just b/.just/remote/react.mod.just new file mode 100644 index 000000000..02b64b06f --- /dev/null +++ b/.just/remote/react.mod.just @@ -0,0 +1,4 @@ +# Local override: run react recipes in the ui/ directory. +set working-directory := '../../ui' + +import? 'react.just' diff --git a/justfile b/justfile index a3b7fce60..06c6dbcf2 100644 --- a/justfile +++ b/justfile @@ -21,7 +21,6 @@ fetch: curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/just.just -o .just/remote/just.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.mod.just -o .just/remote/docker.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.just -o .just/remote/docker.just - curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.mod.just -o .just/remote/react.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.just -o .just/remote/react.just # --- Top-level orchestration --- From 01056d9a825ffcecafe5fc698384ade32b3ed030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sat, 15 Aug 2026 09:54:09 -0700 Subject: [PATCH 4/5] chore: stop tracking stray files netplanStatus.txt is `netplan status --format=json` output from someone's workstation -- MAC addresses, IPv6, flannel and lxd bridges. Nothing reads it. Removed and ignored so it cannot return. .just/remote/react.mod.just was a fetched module forked to point at ui/. The shared react module now takes that path as JUST_REACT_DIR (osapi-justfiles#43), so the fork is unnecessary: the file is untracked, fetch retrieves it like every other module, and the directory is declared here. .gitignore already listed .just/remote/*, which is why the file stayed tracked -- ignore rules do not apply to files already in the index. Co-Authored-By: Claude Opus 5 (1M context) --- .gitignore | 6 ++---- .just/remote/react.mod.just | 4 ---- justfile | 5 +++++ 3 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 .just/remote/react.mod.just diff --git a/.gitignore b/.gitignore index ca07c6e28..7a79256a7 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,5 @@ examples/** !examples/**/*.mod !examples/**/*.sum -# Fetched justfile modules, except osapi's local react override -# (upstream sets working-directory to the repo root; osapi's React app is in ui/) -.just/remote/* -!.just/remote/react.mod.just +# Host network state written by `netplan status --format=json` +netplanStatus.txt diff --git a/.just/remote/react.mod.just b/.just/remote/react.mod.just deleted file mode 100644 index 02b64b06f..000000000 --- a/.just/remote/react.mod.just +++ /dev/null @@ -1,4 +0,0 @@ -# Local override: run react recipes in the ui/ directory. -set working-directory := '../../ui' - -import? 'react.just' diff --git a/justfile b/justfile index 06c6dbcf2..f894d0942 100644 --- a/justfile +++ b/justfile @@ -2,6 +2,10 @@ # Recipes below use `just` subcommands instead of dependency syntax because just # validates dependencies at parse time, which would fail when modules aren't loaded. +# The React application lives in ui/, not at the repository root. The shared +# react module reads this instead of the shim hardcoding a working directory. +export JUST_REACT_DIR := "ui" + mod? go '.just/remote/go.mod.just' mod? docs '.just/remote/docs.mod.just' mod? just '.just/remote/just.mod.just' @@ -21,6 +25,7 @@ fetch: curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/just.just -o .just/remote/just.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.mod.just -o .just/remote/docker.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.just -o .just/remote/docker.just + curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.mod.just -o .just/remote/react.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.just -o .just/remote/react.just # --- Top-level orchestration --- From 0361e61556836c8ddb0e90014c48cf97f5d17c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=CF=85=CE=B1=CE=B7=20=D7=A0=CF=85=CE=B1=CE=B7=D1=95?= =?UTF-8?q?=CF=83=CE=B7?= Date: Sat, 15 Aug 2026 10:09:08 -0700 Subject: [PATCH 5/5] refactor: consume the flat react module Renames react:: call sites to react-, imports react/react.just instead of loading react.mod.just, and declares react_dir in each consuming justfile -- "ui" at the root, "." in ui/justfile. This is what removes .just/remote/react.mod.just from tracking. The file was a fork of a fetched module carrying one per-repository value; with the module flat, the value is declared by the consumer and there is nothing to fork. Depends on osapi-justfiles#44. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/go-int.yml | 4 +-- .github/workflows/go.yml | 2 +- CLAUDE.md | 10 +++---- docs/docs/sidebar/architecture/ui.md | 2 +- docs/docs/sidebar/development/development.md | 4 +-- .../sidebar/development/ui-development.md | 10 +++---- justfile | 26 +++++++++---------- ui/docs/development.md | 6 ++--- ui/justfile | 21 ++++++++------- 9 files changed, 44 insertions(+), 41 deletions(-) diff --git a/.github/workflows/go-int.yml b/.github/workflows/go-int.yml index 076c7b481..970eb8c57 100644 --- a/.github/workflows/go-int.yml +++ b/.github/workflows/go-int.yml @@ -29,9 +29,9 @@ jobs: - name: Deps run: | just go::deps - just react::deps + just react-deps - name: Build UI - run: just react::build + run: just react-build - name: Linux tuning run: just linux-tune - name: Integration diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index d4e804ba3..2a1666731 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -30,7 +30,7 @@ jobs: run: | just go::deps just go::mod - just react::deps + just react-deps - name: Test run: just test - name: Upload coverage reports to Codecov diff --git a/CLAUDE.md b/CLAUDE.md index a0eeef192..3fdb54417 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,10 +32,10 @@ just go::vet # Run golangci-lint just go::fmt # Auto-format (gofumpt + golines) go test -run TestName -v ./internal/job/... # Run a single test -just react::dev # Start UI dev server (http://localhost:5173) -just react::build # Production UI build -just react::lint # Run ESLint on UI -just react::fmt # Format UI with Prettier +just react-dev # Start UI dev server (http://localhost:5173) +just react-build # Production UI build +just react-lint # Run ESLint on UI +just react-fmt # Format UI with Prettier ``` ## Architecture (Quick Reference) @@ -66,7 +66,7 @@ just react::fmt # Format UI with Prettier - **`ui/embed.go`** - `//go:embed dist/*` directive exposing `ui.Assets`. - **`internal/controller/api/ui/`** - SPA serving handler (static files + `index.html` fallback for client-side routing). - Config: `controller.ui.enabled` in `osapi.yaml` (default `true`). -- `//go:embed dist/*` requires `ui/dist/` to have files at compile time. Always use `just build` / `just test` / `just ready` — these run `just react::build` first. Running `go build` / `go test` directly without a prior UI build will fail. +- `//go:embed dist/*` requires `ui/dist/` to have files at compile time. Always use `just build` / `just test` / `just ready` — these run `just react-build` first. Running `go build` / `go test` directly without a prior UI build will fail. ## UI Conventions (MANDATORY) diff --git a/docs/docs/sidebar/architecture/ui.md b/docs/docs/sidebar/architecture/ui.md index ac67d51e4..050325e36 100644 --- a/docs/docs/sidebar/architecture/ui.md +++ b/docs/docs/sidebar/architecture/ui.md @@ -214,7 +214,7 @@ in order: `internal/controller/api/gen/api.yaml`. 2. `go generate` regenerates Go server and SDK code. 3. The combined spec is copied to `ui/src/sdk/gen/api.yaml`. -4. `just react::generate` runs orval against the copied spec to regenerate typed +4. `just react-generate` runs orval against the copied spec to regenerate typed fetch functions and schema types under `ui/src/sdk/gen/`. ### Fetch mutator diff --git a/docs/docs/sidebar/development/development.md b/docs/docs/sidebar/development/development.md index 12e786599..689445439 100644 --- a/docs/docs/sidebar/development/development.md +++ b/docs/docs/sidebar/development/development.md @@ -76,7 +76,7 @@ just build # Builds React UI + Go binary Use `just build` (not `go build` directly). The `//go:embed` directive for the UI assets requires `ui/dist/` to be populated at compile time — `just build` -runs `just react::build` first to satisfy this. The same applies to tests: use +runs `just react-build` first to satisfy this. The same applies to tests: use `just test`, not `go test ./...`. ::: @@ -85,7 +85,7 @@ runs `just react::build` first to satisfy this. The same applies to tests: use The embedded React management dashboard has its own development workflow. See the [UI Development](ui-development.md) guide for prerequisites, the development -server (`just react::dev`), code style, and component conventions. +server (`just react-dev`), code style, and component conventions. ## Documentation diff --git a/docs/docs/sidebar/development/ui-development.md b/docs/docs/sidebar/development/ui-development.md index 36f5ea289..f8627092f 100644 --- a/docs/docs/sidebar/development/ui-development.md +++ b/docs/docs/sidebar/development/ui-development.md @@ -35,13 +35,13 @@ This installs Go modules, Docusaurus dependencies, and the UI's Bun packages. To install only the UI dependencies: ```bash -just react::deps +just react-deps ``` ## Development server ```bash -just react::dev +just react-dev ``` Opens at `http://localhost:5173`. Hot-reloads on file changes. @@ -69,7 +69,7 @@ page. If not set, users paste their token on the sign-in page. just build ``` -This is the top-level build recipe. It runs `just react::build` first (to +This is the top-level build recipe. It runs `just react-build` first (to populate `ui/dist/` with static assets), then `just go::build` to produce the Go binary with the assets embedded via the `//go:embed` directive in `ui/embed.go`. The controller API serves these assets at runtime from the embedded filesystem — @@ -104,8 +104,8 @@ TypeScript and CSS are formatted by [Prettier][] and linted using [ESLint][]. This style is enforced by CI. ```bash -just react::fmt # Auto-fix formatting -just react::lint # Run ESLint +just react-fmt # Auto-fix formatting +just react-lint # Run ESLint ``` ### Component conventions diff --git a/justfile b/justfile index 1043f03f0..e53e7f32c 100644 --- a/justfile +++ b/justfile @@ -8,15 +8,16 @@ # .github/codecov.yml — change both together. export JUST_COVERAGE_TARGET := "99.9" -# The React application lives in ui/, not at the repository root. The shared -# react module reads this instead of the shim hardcoding a working directory. -export JUST_REACT_DIR := "ui" +# The React application lives in ui/, not at the repository root. The flat +# react module requires the importing justfile to declare it. +react_dir := "ui" mod? go '.just/remote/go.mod.just' mod? docs '.just/remote/docs.mod.just' mod? just '.just/remote/just.mod.just' mod? docker '.just/remote/docker.mod.just' -mod? react '.just/remote/react.mod.just' + +import? '.just/remote/react.just' # --- Fetch --- @@ -31,8 +32,7 @@ fetch: curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/just.just -o .just/remote/just.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.mod.just -o .just/remote/docker.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/docker.just -o .just/remote/docker.just - curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.mod.just -o .just/remote/react.mod.just - curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.just -o .just/remote/react.just + curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react/react.just -o .just/remote/react.just # --- Top-level orchestration --- @@ -41,17 +41,17 @@ deps: just go::deps just go::mod just docs::deps - just react::deps + just react-deps # Build production binary (includes embedded UI) build: - just react::build + just react-build go build -o osapi . # Run all tests test: linux-tune just just::fmt-check - just react::build + just react-build just go::test # Generate code @@ -60,7 +60,7 @@ generate: just go::generate just docs::generate cp internal/controller/api/gen/api.yaml ui/src/sdk/gen/api.yaml - just react::generate + just react-generate # Format, lint, and generate before committing ready: @@ -69,9 +69,9 @@ ready: just docs::fmt just go::fmt just go::vet - just react::fmt - just react::lint - just react::build + just react-fmt + just react-lint + just react-build [linux] linux-tune: diff --git a/ui/docs/development.md b/ui/docs/development.md index 13d37a789..aade1f4a4 100644 --- a/ui/docs/development.md +++ b/ui/docs/development.md @@ -80,8 +80,8 @@ TypeScript and CSS should be formatted by [Prettier][] and linted using [ESLint][]. This style is enforced by CI. ```bash -just react::fmt # Auto-fix formatting -just react::lint # Run ESLint +just react-fmt # Auto-fix formatting +just react-lint # Run ESLint ``` ### Component conventions @@ -116,7 +116,7 @@ repo and regenerate the TypeScript SDK: cp /internal/controller/api/gen/api.yaml src/sdk/gen/api.yaml # Regenerate typed fetch functions from the spec: -just react::generate +just react-generate ``` See the [Architecture](architecture.md) docs for the full generation flow. diff --git a/ui/justfile b/ui/justfile index a64311643..ef9507c88 100644 --- a/ui/justfile +++ b/ui/justfile @@ -1,14 +1,17 @@ +# The React application is this directory. +react_dir := "." + # Optional modules: mod? allows `just fetch` to work before .just/remote/ exists. -mod? react '.just/remote/react.mod.just' mod? just '.just/remote/just.mod.just' +import? '.just/remote/react.just' + # --- Fetch --- # Fetch shared justfiles from osapi-justfiles fetch: mkdir -p .just/remote - curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.mod.just -o .just/remote/react.mod.just - curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react.just -o .just/remote/react.just + curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/react/react.just -o .just/remote/react.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/just.mod.just -o .just/remote/just.mod.just curl -sSfL https://raw.githubusercontent.com/osapi-io/osapi-justfiles/refs/heads/main/just.just -o .just/remote/just.just @@ -16,15 +19,15 @@ fetch: # Install all dependencies deps: - just react::deps + just react-deps # Run all tests test: - just react::test + just react-test # Format, lint, generate, and build before committing ready: - just react::generate - just react::fmt - just react::lint - just react::build + just react-generate + just react-fmt + just react-lint + just react-build