Compare commits

..

9 Commits

Author SHA1 Message Date
Aiden McClelland
015ff02d71 fix build 2025-11-20 01:05:50 -07:00
Aiden McClelland
10bfaf5415 fix start-tunnel build 2025-11-20 00:30:33 -07:00
Aiden McClelland
e3e0b85e0c Bugfix/alpha.13 (#3053)
* bugfixes for alpha.13

* minor fixes

* version bump

* start-tunnel workflow

* sdk beta 44

* defaultFilter

* fix reset-password on tunnel auth

* explicitly rebuild types

* fix typo

* ubuntu-latest runner

* add cleanup steps

* fix env on attach
2025-11-19 22:48:49 -07:00
Matt Hill
ad0632892e Various (#3051)
* tell user to restart server after kiosk chnage

* remove unused import

* dont show tor address on server setup

* chore: address comments

* revert mock

* chore: remove uptime block on mobile

* utiliser le futur proche

---------

Co-authored-by: waterplea <alexander@inkin.ru>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>
2025-11-19 10:35:07 -07:00
Aiden McClelland
f26791ba39 fix raspi fsck 2025-11-17 12:17:58 -07:00
Aiden McClelland
2fbaaebf44 Bugfixes for alpha.12 (#3049)
* squashfs-wip

* sdk fixes

* misc fixes

* bump sdk

* Include StartTunnel installation command

Added installation instructions for StartTunnel.

* CA instead of leaf for StartTunnel (#3046)

* updated docs for CA instead of cert

* generate ca instead of self-signed in start-tunnel

* Fix formatting in START-TUNNEL.md installation instructions

* Fix formatting in START-TUNNEL.md

* fix infinite loop

* add success message to install

* hide loopback and bridge gateways

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>
Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com>

* prevent gateways from getting stuck empty

* fix set-password

* misc networking fixes

* build and efi fixes

* efi fixes

* alpha.13

* remove cross

* fix tests

* provide path to upgrade

* fix networkmanager issues

* remove squashfs before creating

---------

Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com>
2025-11-15 22:33:03 -07:00
StuPleb
edb916338c minor typos and grammar (#3047)
* minor typos and grammar

* added missing word - compute
2025-11-14 12:48:41 -07:00
Aiden McClelland
f7e947d37d Fix installation command for StartTunnel (#3048) 2025-11-14 12:42:05 -07:00
Aiden McClelland
a9e3d1ed75 Revise StartTunnel installation and update commands
Updated installation and update instructions for StartTunnel.
2025-11-14 12:39:53 -07:00
434 changed files with 2568 additions and 4045 deletions

100
.github/workflows/start-tunnel.yaml vendored Normal file
View File

@@ -0,0 +1,100 @@
name: Start-Tunnel
on:
workflow_call:
workflow_dispatch:
inputs:
environment:
type: choice
description: Environment
options:
- NONE
- dev
- unstable
- dev-unstable
runner:
type: choice
description: Runner
options:
- standard
- fast
arch:
type: choice
description: Architecture
options:
- ALL
- x86_64
- aarch64
- riscv64
push:
branches:
- master
- next/*
pull_request:
branches:
- master
- next/*
env:
NODEJS_VERSION: "24.11.0"
ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}'
jobs:
compile:
name: Compile Base Binaries
strategy:
fail-fast: true
matrix:
arch: >-
${{
fromJson('{
"x86_64": ["x86_64"],
"aarch64": ["aarch64"],
"riscv64": ["riscv64"],
"ALL": ["x86_64", "aarch64", "riscv64"]
}')[github.event.inputs.platform || 'ALL']
}}
runs-on: ${{ fromJson('["ubuntu-latest", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
steps:
- name: Cleaning up unnecessary files
run: |
sudo apt-get remove --purge -y google-chrome-stable firefox mono-devel
sudo apt-get autoremove -y
sudo apt-get clean
- run: |
sudo mount -t tmpfs tmpfs .
if: ${{ github.event.inputs.runner == 'fast' }}
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODEJS_VERSION }}
- name: Set up docker QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Configure sccache
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Make
run: make tunnel-deb
env:
PLATFORM: ${{ matrix.arch }}
SCCACHE_GHA_ENABLED: on
SCCACHE_GHA_VERSION: 0
- uses: actions/upload-artifact@v4
with:
name: start-tunnel_${{ matrix.arch }}.deb
path: start-tunnel-*_${{ matrix.arch }}.deb

View File

@@ -67,8 +67,13 @@ jobs:
"ALL": ["x86_64", "aarch64"]
}')[github.event.inputs.platform || 'ALL']
}}
runs-on: ${{ fromJson('["ubuntu-22.04", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
runs-on: ${{ fromJson('["ubuntu-latest", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }}
steps:
- name: Cleaning up unnecessary files
run: |
sudo apt-get remove --purge -y google-chrome-stable firefox mono-devel
sudo apt-get autoremove -y
sudo apt-get clean
- run: |
sudo mount -t tmpfs tmpfs .
if: ${{ github.event.inputs.runner == 'fast' }}
@@ -102,12 +107,6 @@ jobs:
core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Use Beta Toolchain
run: rustup default beta
- name: Setup Cross
run: cargo install cross --git https://github.com/cross-rs/cross
- name: Make
run: make ARCH=${{ matrix.arch }} compiled-${{ matrix.arch }}.tar
env:
@@ -140,7 +139,7 @@ jobs:
${{
fromJson(
format(
'["ubuntu-22.04", "{0}"]',
'["ubuntu-latest", "{0}"]',
fromJson('{
"x86_64": "buildjet-8vcpu-ubuntu-2204",
"x86_64-nonfree": "buildjet-8vcpu-ubuntu-2204",
@@ -273,7 +272,7 @@ jobs:
index:
if: ${{ github.event.inputs.deploy != '' && github.event.inputs.deploy != 'NONE' }}
needs: [image]
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- run: >-
curl "https://${{

View File

@@ -17,7 +17,7 @@ env:
jobs:
test:
name: Run Automated Tests
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
@@ -27,11 +27,5 @@ jobs:
with:
node-version: ${{ env.NODEJS_VERSION }}
- name: Use Beta Toolchain
run: rustup default beta
- name: Setup Cross
run: cargo install cross --git https://github.com/cross-rs/cross
- name: Build And Run Tests
run: make test

View File

@@ -40,7 +40,6 @@ STARTOS_TARGETS := $(STARTD_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_
fi')
REGISTRY_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/registrybox core/startos/start-registryd.service
TUNNEL_TARGETS := core/target/$(RUST_ARCH)-unknown-linux-musl/$(PROFILE)/tunnelbox core/startos/start-tunneld.service
REBUILD_TYPES = 1
ifeq ($(REMOTE),)
mkdir = mkdir -p $1
@@ -63,7 +62,7 @@ endif
.DELETE_ON_ERROR:
.PHONY: all metadata install clean format cli uis ui reflash deb $(IMAGE_TYPE) squashfs wormhole wormhole-deb test test-core test-sdk test-container-runtime registry install-registry tunnel install-tunnel
.PHONY: all metadata install clean format cli uis ui reflash deb $(IMAGE_TYPE) squashfs wormhole wormhole-deb test test-core test-sdk test-container-runtime registry install-registry tunnel install-tunnel ts-bindings
all: $(STARTOS_TARGETS)
@@ -160,7 +159,7 @@ results/$(REGISTRY_BASENAME).deb: dpkg-build.sh $(call ls-files,debian/start-reg
tunnel-deb: results/$(TUNNEL_BASENAME).deb
results/$(TUNNEL_BASENAME).deb: dpkg-build.sh $(call ls-files,debian/start-tunnel) $(TUNNEL_TARGETS)
PROJECT=start-tunnel PLATFORM=$(ARCH) REQUIRES=debian DEPENDS=wireguard-tools,iptables ./build/os-compat/run-compat.sh ./dpkg-build.sh
PROJECT=start-tunnel PLATFORM=$(ARCH) REQUIRES=debian DEPENDS=wireguard-tools,iptables,conntrack ./build/os-compat/run-compat.sh ./dpkg-build.sh
$(IMAGE_TYPE): results/$(BASENAME).$(IMAGE_TYPE)
@@ -226,7 +225,7 @@ wormhole-squashfs: results/$(BASENAME).squashfs
$(eval SQFS_SIZE := $(shell du -s --bytes results/$(BASENAME).squashfs | awk '{print $$1}'))
@echo "Paste the following command into the shell of your StartOS server:"
@echo
@wormhole send results/$(BASENAME).squashfs 2>&1 | awk -Winteractive '/wormhole receive/ { printf "sudo sh -c '"'"'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE) && /usr/lib/startos/scripts/prune-boot && cd /media/startos/images && wormhole receive --accept-file %s && CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/use-img ./$(BASENAME).squashfs'"'"'\n", $$3 }'
@wormhole send results/$(BASENAME).squashfs 2>&1 | awk -Winteractive '/wormhole receive/ { printf "sudo sh -c '"'"'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE) && /usr/lib/startos/scripts/prune-boot && cd /media/startos/images && wormhole receive --accept-file %s && CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade ./$(BASENAME).squashfs'"'"'\n", $$3 }'
update: $(STARTOS_TARGETS)
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
@@ -254,7 +253,7 @@ update-squashfs: results/$(BASENAME).squashfs
$(call ssh,'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE)')
$(call ssh,'/usr/lib/startos/scripts/prune-boot')
$(call cp,results/$(BASENAME).squashfs,/media/startos/images/next.rootfs)
$(call ssh,'sudo CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/use-img /media/startos/images/next.rootfs')
$(call ssh,'sudo CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade /media/startos/images/next.rootfs')
emulate-reflash: $(STARTOS_TARGETS)
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
@@ -277,13 +276,15 @@ container-runtime/node_modules/.package-lock.json: container-runtime/package-loc
npm --prefix container-runtime ci
touch container-runtime/node_modules/.package-lock.json
sdk/base/lib/osBindings/index.ts: $(shell if [ "$(REBUILD_TYPES)" -ne 0 ]; then echo core/startos/bindings/index.ts; fi)
ts-bindings: core/startos/bindings/index.ts
mkdir -p sdk/base/lib/osBindings
rsync -ac --delete core/startos/bindings/ sdk/base/lib/osBindings/
touch sdk/base/lib/osBindings/index.ts
core/startos/bindings/index.ts: $(call ls-files, core) $(ENVIRONMENT_FILE)
rm -rf core/startos/bindings
./core/build-ts.sh
ls core/startos/bindings/*.ts | sed 's/core\/startos\/bindings\/\([^.]*\)\.ts/export { \1 } from ".\/\1";/g' | grep -v '"./index"' | tee core/startos/bindings/index.ts
npm --prefix sdk exec -- prettier --config ./sdk/base/package.json -w ./core/startos/bindings/*.ts
touch core/startos/bindings/index.ts
sdk/dist/package.json sdk/baseDist/package.json: $(call ls-files, sdk) sdk/base/lib/osBindings/index.ts

View File

@@ -1,10 +1,18 @@
# StartTunnel
A self-hosted Wiregaurd VPN optimized for creating VLANs and reverse tunneling to personal servers.
A self-hosted WireGuard VPN optimized for creating VLANs and reverse tunneling to personal servers.
You can think of StartTunnel as "virtual router in the cloud"
You can think of StartTunnel as "virtual router in the cloud".
Use it for private, remote access, to self-hosted services running on a personal server, or to expose self-hosted services to the public Internet without revealing the host server's IP address.
Use it for private remote access to self-hosted services running on a personal server, or to expose self-hosted services to the public Internet without revealing the host server's IP address.
## Features
- **Create Subnets**: Each subnet creates a private, virtual local area network (VLAN), similar to the LAN created by a home router.
- **Add Devices**: When you add a device (server, phone, laptop) to a subnet, it receives a LAN IP address on that subnet as well as a unique WireGuard config that must be copied, downloaded, or scanned into the device.
- **Forward Ports**: Forwarding a port creates a "reverse tunnel", exposing a specific port on a specific device to the public Internet.
## Features
@@ -19,7 +27,7 @@ Use it for private, remote access, to self-hosted services running on a personal
1. Rent a low cost VPS. For most use cases, the cheapest option should be enough.
- It must have a dedicated public IP address.
- For (CPU), memory (RAM), and storage (disk), choose the minimum spec.
- For compute (CPU), memory (RAM), and storage (disk), choose the minimum spec.
- For transfer (bandwidth), it depends on (1) your use case and (2) your home Internet's _upload_ speed. Even if you intend to serve large files or stream content from your server, there is no reason to pay for speeds that exceed your home Internet's upload speed.
1. Provision the VPS with the latest version of Debian.
@@ -29,11 +37,17 @@ Use it for private, remote access, to self-hosted services running on a personal
1. Install StartTunnel:
```sh
TMP_DIR=$(mktemp -d) && (cd $TMP_DIR && wget https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.12/start-tunnel-0.4.0-alpha.12-68f401b_$(uname -m).deb && apt-get install -y ./start-tunnel-0.4.0-alpha.12-68f401b_$(uname -m).deb) && rm -rf $TMP_DIR && systemctl start start-tunneld && echo "Installation Succeeded"
TMP_DIR=$(mktemp -d) && (cd $TMP_DIR && wget https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.12/start-tunnel-0.4.0-alpha.12-unknown.dev_$(uname -m).deb && apt-get install -y ./start-tunnel-0.4.0-alpha.12-unknown.dev_$(uname -m).deb) && rm -rf $TMP_DIR && systemctl start start-tunneld && echo "Installation Succeeded"
```
5. [Initialize the web interface](#web-interface) (recommended)
## Updating
```sh
TMP_DIR=$(mktemp -d) && (cd $TMP_DIR && wget https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.12/start-tunnel-0.4.0-alpha.12-unknown.dev_$(uname -m).deb && apt-get install --reinstall -y ./start-tunnel-0.4.0-alpha.12-unknown.dev_$(uname -m).deb) && rm -rf $TMP_DIR && systemctl daemon-reload && systemctl restart start-tunneld && echo "Update Succeeded"
```
## CLI
By default, StartTunnel is managed via the `start-tunnel` command line interface, which is self-documented.

View File

@@ -7,6 +7,7 @@ bmon
btrfs-progs
ca-certificates
cifs-utils
conntrack
cryptsetup
curl
dmidecode
@@ -19,7 +20,6 @@ flashrom
fuse3
grub-common
grub-efi
grub2-common
htop
httpdirfs
iotop

View File

@@ -1,6 +1,4 @@
- grub-common
- grub-efi
- grub2-common
+ parted
+ raspberrypi-net-mods
+ raspberrypi-sys-mods

View File

@@ -10,24 +10,24 @@ fi
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
--no-sync)
NO_SYNC=1
shift
;;
--create)
ONLY_CREATE=1
shift
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
case $1 in
--no-sync)
NO_SYNC=1
shift
;;
--create)
ONLY_CREATE=1
shift
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
@@ -35,7 +35,7 @@ set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [ -z "$NO_SYNC" ]; then
echo 'Syncing...'
umount -R /media/startos/next 2> /dev/null
umount -R /media/startos/upper 2> /dev/null
umount /media/startos/upper 2> /dev/null
rm -rf /media/startos/upper /media/startos/next
mkdir /media/startos/upper
mount -t tmpfs tmpfs /media/startos/upper
@@ -43,8 +43,6 @@ if [ -z "$NO_SYNC" ]; then
mount -t overlay \
-olowerdir=/media/startos/current,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
overlay /media/startos/next
mkdir -p /media/startos/next/media/startos/root
mount --bind /media/startos/root /media/startos/next/media/startos/root
fi
if [ -n "$ONLY_CREATE" ]; then
@@ -56,12 +54,18 @@ mkdir -p /media/startos/next/dev
mkdir -p /media/startos/next/sys
mkdir -p /media/startos/next/proc
mkdir -p /media/startos/next/boot
mkdir -p /media/startos/next/media/startos/root
mount --bind /run /media/startos/next/run
mount --bind /tmp /media/startos/next/tmp
mount --bind /dev /media/startos/next/dev
mount --bind /sys /media/startos/next/sys
mount --bind /proc /media/startos/next/proc
mount --bind /boot /media/startos/next/boot
mount --bind /media/startos/root /media/startos/next/media/startos/root
if mountpoint /sys/firmware/efi/efivars 2> /dev/null; then
mount --bind /sys/firmware/efi/efivars /media/startos/next/sys/firmware/efi/efivars
fi
if [ -z "$*" ]; then
chroot /media/startos/next
@@ -71,6 +75,10 @@ else
CHROOT_RES=$?
fi
if mountpoint /media/startos/next/sys/firmware/efi/efivars 2> /dev/null; then
umount /media/startos/next/sys/firmware/efi/efivars
fi
umount /media/startos/next/run
umount /media/startos/next/tmp
umount /media/startos/next/dev
@@ -87,11 +95,12 @@ if [ "$CHROOT_RES" -eq 0 ]; then
echo 'Upgrading...'
rm -f /media/startos/images/next.squashfs
if ! time mksquashfs /media/startos/next /media/startos/images/next.squashfs -b 4096 -comp gzip; then
umount -R /media/startos/next
umount -R /media/startos/upper
rm -rf /media/startos/upper /media/startos/next
exit 1
umount -l /media/startos/next
umount -l /media/startos/upper
rm -rf /media/startos/upper /media/startos/next
exit 1
fi
hash=$(b3sum /media/startos/images/next.squashfs | head -c 32)
mv /media/startos/images/next.squashfs /media/startos/images/${hash}.rootfs
@@ -103,5 +112,5 @@ if [ "$CHROOT_RES" -eq 0 ]; then
fi
umount -R /media/startos/next
umount -R /media/startos/upper
umount /media/startos/upper
rm -rf /media/startos/upper /media/startos/next

View File

@@ -5,34 +5,25 @@ if [ -z "$sip" ] || [ -z "$dip" ] || [ -z "$sport" ] || [ -z "$dport" ]; then
exit 1
fi
# Helper function to check if a rule exists
nat_rule_exists() {
rule_exists() {
iptables -t nat -C "$@" 2>/dev/null
}
# Helper function to add or delete a rule idempotently
# Usage: apply_rule [add|del] <iptables args...>
apply_nat_rule() {
local action="$1"
shift
if [ "$action" = "add" ]; then
# Only add if rule doesn't exist
if ! rule_exists "$@"; then
iptables -t nat -A "$@"
fi
elif [ "$action" = "del" ]; then
apply_rule() {
if [ "$UNDO" = "1" ]; then
if rule_exists "$@"; then
iptables -t nat -D "$@"
fi
else
if ! rule_exists "$@"; then
iptables -t nat -A "$@"
fi
fi
}
if [ "$UNDO" = 1 ]; then
action="del"
else
action="add"
fi
apply_rule PREROUTING -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport
apply_rule OUTPUT -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport
apply_nat_rule "$action" PREROUTING -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport
apply_nat_rule "$action" OUTPUT -p tcp -d $sip --dport $sport -j DNAT --to-destination $dip:$dport
if [ "$UNDO" = 1 ]; then
conntrack -D -p tcp -d $sip --dport $sport || true # conntrack returns exit 1 if no connections are active
fi

82
build/lib/scripts/upgrade Executable file
View File

@@ -0,0 +1,82 @@
#!/bin/bash
set -e
SOURCE_DIR="$(dirname $(realpath "${BASH_SOURCE[0]}"))"
if [ "$UID" -ne 0 ]; then
>&2 echo 'Must be run as root'
exit 1
fi
if ! [ -f "$1" ]; then
>&2 echo "usage: $0 <SQUASHFS>"
exit 1
fi
echo 'Upgrading...'
hash=$(b3sum $1 | head -c 32)
if [ -n "$2" ] && [ "$hash" != "$CHECKSUM" ]; then
>&2 echo 'Checksum mismatch'
exit 2
fi
unsquashfs -f -d / $1 boot
umount -R /media/startos/next 2> /dev/null || true
umount /media/startos/upper 2> /dev/null || true
umount /media/startos/lower 2> /dev/null || true
mkdir -p /media/startos/upper
mount -t tmpfs tmpfs /media/startos/upper
mkdir -p /media/startos/lower /media/startos/upper/data /media/startos/upper/work /media/startos/next
mount $1 /media/startos/lower
mount -t overlay \
-olowerdir=/media/startos/lower,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
overlay /media/startos/next
mkdir -p /media/startos/next/run
mkdir -p /media/startos/next/dev
mkdir -p /media/startos/next/sys
mkdir -p /media/startos/next/proc
mkdir -p /media/startos/next/boot
mkdir -p /media/startos/next/media/startos/root
mount --bind /run /media/startos/next/run
mount --bind /tmp /media/startos/next/tmp
mount --bind /dev /media/startos/next/dev
mount --bind /sys /media/startos/next/sys
mount --bind /proc /media/startos/next/proc
mount --bind /boot /media/startos/next/boot
mount --bind /media/startos/root /media/startos/next/media/startos/root
if mountpoint /boot/efi 2> /dev/null; then
mkdir -p /media/startos/next/boot/efi
mount --bind /boot/efi /media/startos/next/boot/efi
fi
if mountpoint /sys/firmware/efi/efivars 2> /dev/null; then
mount --bind /sys/firmware/efi/efivars /media/startos/next/sys/firmware/efi/efivars
fi
chroot /media/startos/next bash -e << "EOF"
if dpkg -s grub-common 2>&1 > /dev/null; then
grub-install /dev/$(eval $(lsblk -o MOUNTPOINT,PKNAME -P | grep 'MOUNTPOINT="/media/startos/root"') && echo $PKNAME)
update-grub
fi
EOF
sync
umount -R /media/startos/next
umount /media/startos/upper
umount /media/startos/lower
mv $1 /media/startos/images/${hash}.rootfs
ln -rsf /media/startos/images/${hash}.rootfs /media/startos/config/current.rootfs
sync
echo 'System upgrade complete. Reboot to apply changes...'

View File

@@ -1,61 +0,0 @@
#!/bin/bash
set -e
if [ "$UID" -ne 0 ]; then
>&2 echo 'Must be run as root'
exit 1
fi
if [ -z "$1" ]; then
>&2 echo "usage: $0 <SQUASHFS>"
exit 1
fi
VERSION=$(unsquashfs -cat $1 /usr/lib/startos/VERSION.txt)
GIT_HASH=$(unsquashfs -cat $1 /usr/lib/startos/GIT_HASH.txt)
B3SUM=$(b3sum $1 | head -c 32)
if [ -n "$CHECKSUM" ] && [ "$CHECKSUM" != "$B3SUM" ]; then
>&2 echo "CHECKSUM MISMATCH"
exit 2
fi
mv $1 /media/startos/images/${B3SUM}.rootfs
ln -rsf /media/startos/images/${B3SUM}.rootfs /media/startos/config/current.rootfs
unsquashfs -n -f -d / /media/startos/images/${B3SUM}.rootfs boot
umount -R /media/startos/next 2> /dev/null || true
umount -R /media/startos/lower 2> /dev/null || true
umount -R /media/startos/upper 2> /dev/null || true
rm -rf /media/startos/lower /media/startos/upper /media/startos/next
mkdir /media/startos/upper
mount -t tmpfs tmpfs /media/startos/upper
mkdir -p /media/startos/lower /media/startos/upper/data /media/startos/upper/work /media/startos/next
mount /media/startos/images/${B3SUM}.rootfs /media/startos/lower
mount -t overlay \
-olowerdir=/media/startos/lower,upperdir=/media/startos/upper/data,workdir=/media/startos/upper/work \
overlay /media/startos/next
mkdir -p /media/startos/next/media/startos/root
mount --bind /media/startos/root /media/startos/next/media/startos/root
mkdir -p /media/startos/next/dev
mkdir -p /media/startos/next/sys
mkdir -p /media/startos/next/proc
mkdir -p /media/startos/next/boot
mount --bind /dev /media/startos/next/dev
mount --bind /sys /media/startos/next/sys
mount --bind /proc /media/startos/next/proc
mount --bind /boot /media/startos/next/boot
chroot /media/startos/next update-grub2
umount -R /media/startos/next
umount -R /media/startos/upper
umount -R /media/startos/lower
rm -rf /media/startos/lower /media/startos/upper /media/startos/next
sync
reboot

View File

@@ -38,7 +38,7 @@
},
"../sdk/dist": {
"name": "@start9labs/start-sdk",
"version": "0.4.0-beta.43",
"version": "0.4.0-beta.44",
"license": "MIT",
"dependencies": {
"@iarna/toml": "^3.0.0",

View File

@@ -158,6 +158,8 @@ export class RpcListener {
this.unixSocketServer.listen(SOCKET_PATH)
console.log("Listening on %s", SOCKET_PATH)
this.unixSocketServer.on("connection", (s) => {
let id: IdType = null
const captureId = <X>(x: X) => {

View File

@@ -9,7 +9,7 @@ if [ "$ARCH" = "riscv64" ]; then
RUST_ARCH="riscv64gc"
fi
if mountpoint -q tmp/combined; then sudo umount -R tmp/combined; fi
if mountpoint -q tmp/combined; then sudo umount -l tmp/combined; fi
if mountpoint -q tmp/lower; then sudo umount tmp/lower; fi
sudo rm -rf tmp
mkdir -p tmp/lower tmp/upper tmp/work tmp/combined

302
core/Cargo.lock generated
View File

@@ -270,7 +270,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [
"async-trait",
"cfg-if",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"educe",
@@ -367,7 +367,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"synstructure",
]
@@ -379,7 +379,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"synstructure",
]
@@ -391,7 +391,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -459,9 +459,9 @@ dependencies = [
[[package]]
name = "async-compression"
version = "0.4.33"
version = "0.4.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93c1f86859c1af3d514fa19e8323147ff10ea98684e6c7b307912509f50e67b2"
checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0"
dependencies = [
"compression-codecs",
"compression-core",
@@ -567,7 +567,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -634,7 +634,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -651,7 +651,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -989,7 +989,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -1107,7 +1107,7 @@ checksum = "e0b121a9fe0df916e362fb3271088d071159cdf11db0e4182d02152850756eff"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -1247,9 +1247,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.45"
version = "1.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe"
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -1404,7 +1404,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -1497,9 +1497,9 @@ dependencies = [
[[package]]
name = "compression-codecs"
version = "0.4.32"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "680dc087785c5230f8e8843e2e57ac7c1c90488b6a91b88caa265410568f441b"
checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23"
dependencies = [
"brotli",
"compression-core",
@@ -1512,9 +1512,9 @@ dependencies = [
[[package]]
name = "compression-core"
version = "0.4.30"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9b614a5787ef0c8802a55766480563cb3a93b435898c422ed2a359cf811582"
checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb"
[[package]]
name = "concurrent-queue"
@@ -2011,7 +2011,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2059,7 +2059,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2081,7 +2081,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core 0.21.3",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2138,7 +2138,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2151,16 +2151,44 @@ dependencies = [
"serde_core",
]
[[package]]
name = "derive-deftly"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8ea84d0109517cc2253d4a679bdda1e8989e9bd86987e9e4f75ffdda0095fd1"
dependencies = [
"derive-deftly-macros 0.14.6",
"heck 0.5.0",
]
[[package]]
name = "derive-deftly"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957bb73a3a9c0bbcac67e129b81954661b3cfcb9e28873d8441f91b54852e77a"
dependencies = [
"derive-deftly-macros",
"derive-deftly-macros 1.2.0",
"heck 0.5.0",
]
[[package]]
name = "derive-deftly-macros"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357422a457ccb850dc8f1c1680e0670079560feaad6c2e247e3f345c4fab8a3f"
dependencies = [
"heck 0.5.0",
"indexmap 2.12.0",
"itertools 0.14.0",
"proc-macro-crate",
"proc-macro2",
"quote",
"sha3 0.10.8",
"strum",
"syn 2.0.108",
"void",
]
[[package]]
name = "derive-deftly-macros"
version = "1.2.0"
@@ -2175,7 +2203,7 @@ dependencies = [
"quote",
"sha3 0.10.8",
"strum",
"syn 2.0.110",
"syn 2.0.108",
"void",
]
@@ -2187,7 +2215,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2231,7 +2259,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2252,7 +2280,7 @@ dependencies = [
"convert_case 0.7.1",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"unicode-xid",
]
@@ -2342,7 +2370,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2423,7 +2451,7 @@ dependencies = [
"proc-macro-error2",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2617,7 +2645,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2630,7 +2658,7 @@ dependencies = [
"num-traits",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -2651,7 +2679,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -3085,7 +3113,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -3430,7 +3458,7 @@ dependencies = [
"lazy_async_pool",
"models",
"pin-project",
"rpc-toolkit",
"rpc-toolkit 0.3.2 (git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master)",
"serde",
"serde_json",
"tokio",
@@ -3851,9 +3879,9 @@ dependencies = [
[[package]]
name = "iddqd"
version = "0.3.16"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dda610d939ea51890ca6c827c8365acf0a44b4b53d2ed6f371e8e7e47bc75d25"
checksum = "bac5efd33e0c5eb0ac45cbd210541a214dac576896ca97ba08e16e3b1079cdd8"
dependencies = [
"allocator-api2",
"equivalent",
@@ -4739,7 +4767,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -4807,7 +4835,7 @@ dependencies = [
"rand 0.9.2",
"regex",
"reqwest",
"rpc-toolkit",
"rpc-toolkit 0.3.2 (git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master)",
"rustls 0.23.35",
"serde",
"serde_json",
@@ -5122,7 +5150,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5285,9 +5313,9 @@ dependencies = [
[[package]]
name = "openssl"
version = "0.10.75"
version = "0.10.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654"
dependencies = [
"bitflags 2.10.0",
"cfg-if",
@@ -5306,7 +5334,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5326,9 +5354,9 @@ dependencies = [
[[package]]
name = "openssl-sys"
version = "0.9.111"
version = "0.9.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2"
dependencies = [
"cc",
"libc",
@@ -5490,7 +5518,7 @@ dependencies = [
"nix 0.30.1",
"patch-db-macro",
"serde",
"serde_cbor 0.11.1",
"serde_cbor",
"thiserror 2.0.17",
"tokio",
"tracing",
@@ -5581,7 +5609,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5655,7 +5683,7 @@ dependencies = [
"phf_shared 0.11.3",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5668,7 +5696,7 @@ dependencies = [
"phf_shared 0.13.1",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5712,7 +5740,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5919,7 +5947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -5984,7 +6012,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -6048,7 +6076,7 @@ checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -6071,7 +6099,7 @@ dependencies = [
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -6120,14 +6148,14 @@ dependencies = [
[[package]]
name = "pwd-grp"
version = "1.0.2"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e2023f41b5fcb7c30eb5300a5733edfaa9e0e0d502d51b586f65633fd39e40c"
checksum = "b94fdf3867b7f2889a736f0022ea9386766280d2cca4bdbe41629ada9e4f3b8f"
dependencies = [
"derive-deftly",
"derive-deftly 0.14.6",
"libc",
"paste",
"thiserror 2.0.17",
"thiserror 1.0.69",
]
[[package]]
@@ -6220,9 +6248,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.42"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
@@ -6549,7 +6577,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -6691,7 +6719,35 @@ dependencies = [
[[package]]
name = "rpc-toolkit"
version = "0.3.2"
source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master#2dd2832e043eb5380c91cf80f3e78a700d204be3"
source = "git+https://github.com/Start9Labs/rpc-toolkit.git?branch=master#068db905ee38a7da97cc4a43b806409204e73723"
dependencies = [
"async-stream",
"async-trait",
"axum 0.8.6",
"clap",
"futures",
"http",
"http-body-util",
"imbl-value 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.14.0",
"lazy_format",
"lazy_static",
"openssl",
"pin-project",
"reqwest",
"serde",
"serde_json",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"url",
"yajrc",
]
[[package]]
name = "rpc-toolkit"
version = "0.3.2"
source = "git+https://github.com/Start9Labs/rpc-toolkit.git?rev=068db90#068db905ee38a7da97cc4a43b806409204e73723"
dependencies = [
"async-stream",
"async-trait",
@@ -6708,12 +6764,10 @@ dependencies = [
"pin-project",
"reqwest",
"serde",
"serde_cbor 0.11.2",
"serde_json",
"thiserror 2.0.17",
"tokio",
"tokio-stream",
"ts-rs",
"url",
"yajrc",
]
@@ -7019,9 +7073,9 @@ dependencies = [
[[package]]
name = "schemars"
version = "1.1.0"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289"
checksum = "1317c3bf3e7df961da95b0a56a172a02abead31276215a0497241a7624b487ce"
dependencies = [
"dyn-clone",
"ref-cast",
@@ -7148,16 +7202,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half 1.8.3",
"serde",
]
[[package]]
name = "serde_core"
version = "1.0.228"
@@ -7175,7 +7219,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -7232,7 +7276,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -7277,7 +7321,7 @@ dependencies = [
"indexmap 1.9.3",
"indexmap 2.12.0",
"schemars 0.9.0",
"schemars 1.1.0",
"schemars 1.0.5",
"serde_core",
"serde_json",
"serde_with_macros",
@@ -7293,7 +7337,7 @@ dependencies = [
"darling 0.21.3",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -7711,7 +7755,7 @@ dependencies = [
"quote",
"sqlx-core",
"sqlx-macros-core",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -7732,7 +7776,7 @@ dependencies = [
"sha2 0.10.9",
"sqlx-core",
"sqlx-postgres",
"syn 2.0.110",
"syn 2.0.108",
"tokio",
"url",
]
@@ -7797,7 +7841,7 @@ dependencies = [
"quote",
"regex-syntax 0.6.29",
"strsim 0.11.1",
"syn 2.0.110",
"syn 2.0.108",
"unicode-width 0.1.14",
]
@@ -7864,7 +7908,7 @@ dependencies = [
[[package]]
name = "start-os"
version = "0.4.0-alpha.12"
version = "0.4.0-alpha.14"
dependencies = [
"aes 0.7.5",
"arti-client",
@@ -7872,7 +7916,6 @@ dependencies = [
"async-compression",
"async-stream",
"async-trait",
"aws-lc-sys",
"axum 0.8.6",
"backtrace-on-stack-overflow",
"barrage",
@@ -7965,7 +8008,7 @@ dependencies = [
"reqwest",
"reqwest_cookie_store",
"rpassword",
"rpc-toolkit",
"rpc-toolkit 0.3.2 (git+https://github.com/Start9Labs/rpc-toolkit.git?rev=068db90)",
"rust-argon2",
"safelog",
"semver",
@@ -8098,7 +8141,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -8141,9 +8184,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.110"
version = "2.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
dependencies = [
"proc-macro2",
"quote",
@@ -8167,7 +8210,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -8335,7 +8378,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -8346,7 +8389,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -8471,7 +8514,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -8707,7 +8750,7 @@ name = "tor-async-utils"
version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"derive-deftly",
"derive-deftly 1.2.0",
"educe",
"futures",
"oneshot-fused-workaround",
@@ -8741,7 +8784,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"bytes",
"derive-deftly",
"derive-deftly 1.2.0",
"digest 0.10.7",
"educe",
"getrandom 0.3.4",
@@ -8761,7 +8804,7 @@ dependencies = [
"bitflags 2.10.0",
"bytes",
"caret",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"educe",
"itertools 0.14.0",
@@ -8852,7 +8895,7 @@ dependencies = [
"async-trait",
"bounded-vec-deque",
"cfg-if",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"downcast-rs 2.0.2",
@@ -8899,7 +8942,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [
"amplify",
"cfg-if",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"educe",
"either",
@@ -9062,7 +9105,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [
"amplify",
"base64ct",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"dyn-clone",
@@ -9102,7 +9145,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"async-trait",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"educe",
"either",
@@ -9146,7 +9189,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [
"cipher 0.4.4",
"data-encoding",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"digest 0.10.7",
"equix",
@@ -9180,7 +9223,7 @@ dependencies = [
"async-trait",
"base64ct",
"cfg-if",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"digest 0.10.7",
@@ -9233,7 +9276,7 @@ name = "tor-key-forge"
version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"downcast-rs 2.0.2",
"paste",
@@ -9256,7 +9299,7 @@ dependencies = [
"amplify",
"arrayvec 0.7.6",
"cfg-if",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"downcast-rs 2.0.2",
@@ -9295,7 +9338,7 @@ dependencies = [
"base64ct",
"by_address",
"caret",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"hex",
@@ -9323,7 +9366,7 @@ dependencies = [
"ctr 0.9.2",
"curve25519-dalek 4.1.3",
"der-parser 10.0.0",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"digest 0.10.7",
"ed25519-dalek 2.2.0",
@@ -9371,7 +9414,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"cfg-if",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"dyn-clone",
"educe",
@@ -9435,7 +9478,7 @@ dependencies = [
"base64ct",
"bitflags 2.10.0",
"cipher 0.4.4",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"digest 0.10.7",
@@ -9478,7 +9521,7 @@ version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"amplify",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"filetime",
"fs-mistrust",
@@ -9514,7 +9557,7 @@ dependencies = [
"cipher 0.4.4",
"coarsetime",
"criterion-cycles-per-byte",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_builder_fork_arti",
"derive_more 2.0.1",
"digest 0.10.7",
@@ -9629,7 +9672,7 @@ dependencies = [
"amplify",
"assert_matches",
"async-trait",
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"educe",
"futures",
@@ -9656,7 +9699,7 @@ source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit
dependencies = [
"amplify",
"caret",
"derive-deftly",
"derive-deftly 1.2.0",
"educe",
"safelog",
"subtle",
@@ -9670,7 +9713,7 @@ name = "tor-units"
version = "0.33.0"
source = "git+https://github.com/Start9Labs/arti.git?branch=patch%2Fdisable-exit#24730694701a83432d791d80802db8bda0699700"
dependencies = [
"derive-deftly",
"derive-deftly 1.2.0",
"derive_more 2.0.1",
"serde",
"thiserror 2.0.17",
@@ -9795,7 +9838,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -9886,7 +9929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568"
dependencies = [
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -9901,7 +9944,6 @@ version = "9.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b44017f9f875786e543595076374b9ef7d13465a518dd93d6ccdbf5b432dde8c"
dependencies = [
"chrono",
"thiserror 1.0.69",
"ts-rs-macros",
]
@@ -9914,7 +9956,7 @@ checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"termcolor",
]
@@ -9971,7 +10013,7 @@ checksum = "1ecb9ecf7799210407c14a8cfdfe0173365780968dc57973ed082211958e0b18"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -10199,7 +10241,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -10222,7 +10264,7 @@ checksum = "de41688745bbd6ed24e2f4923026911b523f0c057e10f86f44652a20e65555ce"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -10349,7 +10391,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"wasm-bindgen-shared",
]
@@ -10630,7 +10672,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -10641,7 +10683,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -11230,7 +11272,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"synstructure",
]
@@ -11277,7 +11319,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"zbus_names",
"zvariant",
"zvariant_utils",
@@ -11312,7 +11354,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -11332,7 +11374,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"synstructure",
]
@@ -11353,7 +11395,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -11387,7 +11429,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
]
[[package]]
@@ -11441,7 +11483,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.110",
"syn 2.0.108",
"zvariant_utils",
]
@@ -11454,6 +11496,6 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.110",
"syn 2.0.108",
"winnow",
]

View File

@@ -1,5 +1,2 @@
[build]
pre-build = ["apt-get update && apt-get install -y rsync"]
[build.env]
passthrough = ["RUST_BACKTRACE"]

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "${ARCH:-}" ]; then
@@ -18,15 +25,20 @@ if [ "$ARCH" = "arm64" ]; then
ARCH="aarch64"
fi
RUST_ARCH="$ARCH"
if [ "$ARCH" = "riscv64" ]; then
RUST_ARCH="riscv64gc"
fi
if [ -z "${KERNEL_NAME:-}" ]; then
KERNEL_NAME=$(uname -s)
fi
if [ -z "${TARGET:-}" ]; then
if [ "$KERNEL_NAME" = "Linux" ]; then
TARGET="$ARCH-unknown-linux-musl"
TARGET="$RUST_ARCH-unknown-linux-musl"
elif [ "$KERNEL_NAME" = "Darwin" ]; then
TARGET="$ARCH-apple-darwin"
TARGET="$RUST_ARCH-apple-darwin"
else
>&2 echo "unknown kernel $KERNEL_NAME"
exit 1
@@ -53,4 +65,7 @@ fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features $FEATURE_ARGS --locked --bin start-cli --target=$TARGET
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features $FEATURE_ARGS --locked --bin start-cli --target=$TARGET
if [ "$(ls -nd "core/target/$TARGET/$PROFILE/start-cli" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "cd core && chown -R $UID:$UID target && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
@@ -33,4 +40,7 @@ fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-container,$FEATURES --locked --bin containerbox --target=$RUST_ARCH-unknown-linux-musl
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-container,$FEATURES --locked --bin containerbox --target=$RUST_ARCH-unknown-linux-musl
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/containerbox" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
@@ -33,4 +40,7 @@ fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-registry,registry,$FEATURES --locked --bin registrybox --target=$RUST_ARCH-unknown-linux-musl
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-registry,registry,$FEATURES --locked --bin registrybox --target=$RUST_ARCH-unknown-linux-musl
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/registrybox" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
@@ -33,4 +40,7 @@ fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli,startd,$FEATURES --locked --bin startbox --target=$RUST_ARCH-unknown-linux-musl
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli,startd,$FEATURES --locked --bin startbox --target=$RUST_ARCH-unknown-linux-musl
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/startbox" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
@@ -24,9 +31,6 @@ if [ "$ARCH" = "riscv64" ]; then
fi
cd ..
rm -rf core/startos/bindings/
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
RUSTFLAGS=""
if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
@@ -34,16 +38,7 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features test,$FEATURES --locked 'export_bindings_'
cd core/startos/bindings
for folder in $(find . -type d); do
(
cd $folder
find . -name '*.ts' -maxdepth 1 | sed 's/\.\/\([^.]*\)\.ts/export * from ".\/\1";/g' | grep -v '"./index"' | tee ./index.ts
find . -mindepth 1 -maxdepth 1 -type d | sed 's/\.\/\([^.]*\)/export * as \1 from ".\/\1";/g' | grep -v '"./index"' | tee -a ./index.ts
)
done
find . -name '*.ts' | xargs -P $(nproc) -I % npm --prefix ../../../sdk exec -- prettier --config ../../../sdk/base/package.json -w %
rust-zig-builder cargo test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features test,$FEATURES --locked 'export_bindings_'
if [ "$(ls -nd "core/startos/bindings" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID core/startos/bindings && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
@@ -33,4 +40,7 @@ fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross build --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-tunnel,tunnel,$FEATURES --locked --bin tunnelbox --target=$RUST_ARCH-unknown-linux-musl
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --no-default-features --features cli-tunnel,tunnel,$FEATURES --locked --bin tunnelbox --target=$RUST_ARCH-unknown-linux-musl
if [ "$(ls -nd "core/target/$RUST_ARCH-unknown-linux-musl/$PROFILE/tunnelbox" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /root/.cargo"
fi

View File

@@ -1,3 +1,8 @@
#!/bin/bash
alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -e SCCACHE_GHA_ENABLED -e SCCACHE_GHA_VERSION -e ACTIONS_RESULTS_URL -e ACTIONS_RUNTIME_TOKEN -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$HOME/.cache/sccache":/root/.cache/sccache -v "$(pwd)":/home/rust/src -w /home/rust/src -P start9/rust-musl-cross:$ARCH-musl'
USE_TTY=
if tty -s; then
USE_TTY="-it"
fi
alias 'rust-zig-builder'='docker run '"$USE_TTY"' --rm -e "RUSTFLAGS=$RUSTFLAGS" -e "AWS_LC_SYS_CMAKE_TOOLCHAIN_FILE_riscv64gc_unknown_linux_musl=/root/cmake-overrides/toolchain-riscv64-musl-clang.cmake" -e SCCACHE_GHA_ENABLED -e SCCACHE_GHA_VERSION -e ACTIONS_RESULTS_URL -e ACTIONS_RUNTIME_TOKEN -v "$HOME/.cargo/registry":/usr/local/cargo/registry -v "$HOME/.cargo/git":/root/.cargo/git -v "$HOME/.cache/sccache":/root/.cache/sccache -v "$(pwd)":/workdir -w /workdir -P start9/cargo-zigbuild'

View File

@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ServiceInterfaceId = string;

View File

@@ -8,7 +8,7 @@ use ts_rs::TS;
use crate::{FromStrParser, Id};
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, TS)]
#[ts(type = "string")]
#[ts(export, type = "string")]
pub struct ServiceInterfaceId(Id);
impl From<Id> for ServiceInterfaceId {
fn from(id: Id) -> Self {

View File

@@ -2,12 +2,19 @@
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-release}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug"]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
@@ -31,8 +38,8 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable"
fi
source ./core/builder-alias.sh
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
cross test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=test,$FEATURES --workspace --locked --target=$ARCH-unknown-linux-musl -- --skip export_bindings_
rust-zig-builder cargo test --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=test,$FEATURES --workspace --locked -- --skip export_bindings_
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID /root/.cargo"

View File

@@ -15,7 +15,7 @@ license = "MIT"
name = "start-os"
readme = "README.md"
repository = "https://github.com/Start9Labs/start-os"
version = "0.4.0-alpha.12" # VERSION_BUMP
version = "0.4.0-alpha.14" # VERSION_BUMP
[lib]
name = "startos"
@@ -93,7 +93,6 @@ async-compression = { version = "0.4.32", features = [
] }
async-stream = "0.3.5"
async-trait = "0.1.74"
aws-lc-sys = { version = "0.32", features = ["bindgen"] }
axum = { version = "0.8.4", features = ["ws"] }
backtrace-on-stack-overflow = { version = "0.3.0", optional = true }
barrage = "0.2.3"
@@ -223,7 +222,7 @@ regex = "1.10.2"
reqwest = { version = "0.12.4", features = ["json", "socks", "stream"] }
reqwest_cookie_store = "0.8.0"
rpassword = "7.2.0"
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", branch = "master" }
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git", rev = "068db90" }
rust-argon2 = "2.0.0"
safelog = { version = "0.4.8", git = "https://github.com/Start9Labs/arti.git", branch = "patch/disable-exit", optional = true }
semver = { version = "1.0.20", features = ["serde"] }
@@ -252,7 +251,7 @@ termion = "4.0.5"
textwrap = "0.16.1"
thiserror = "2.0.12"
tokio = { version = "1.38.1", features = ["full"] }
tokio-rustls = "0.26.0"
tokio-rustls = "0.26.4"
tokio-stream = { version = "0.1.14", features = ["io-util", "net", "sync"] }
tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" }
tokio-tungstenite = { version = "0.26.2", features = ["native-tls", "url"] }
@@ -280,7 +279,7 @@ tracing-error = "0.2.0"
tracing-futures = "0.2.5"
tracing-journald = "0.3.0"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
ts-rs = { version = "9.0.1", features = ["chrono-impl"] }
ts-rs = "9.0.1"
typed-builder = "0.21.0"
unix-named-pipe = "0.2.0"
url = { version = "2.4.1", features = ["serde"] }

View File

@@ -4,7 +4,7 @@ use clap::{CommandFactory, FromArgMatches, Parser};
pub use models::ActionId;
use models::{PackageId, ReplayId};
use qrcode::QrCode;
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize};
use tracing::instrument;
use ts_rs::TS;
@@ -14,22 +14,9 @@ use crate::db::model::package::TaskSeverity;
use crate::prelude::*;
use crate::rpc_continuations::Guid;
use crate::util::serde::{
display_serializable, HandlerExtSerde, StdinDeserializable, WithIoFormat,
HandlerExtSerde, StdinDeserializable, WithIoFormat, display_serializable,
};
#[test]
fn export_bindings_action() {
use crate::db::model::package::{ActionMetadata, Task};
const OUT_DIR: &str = "./bindings/action";
ActionId::export_all_to(OUT_DIR).unwrap();
ActionInput::export_all_to(OUT_DIR).unwrap();
ActionResult::export_all_to(OUT_DIR).unwrap();
ActionMetadata::export_all_to(OUT_DIR).unwrap();
Task::export_all_to(OUT_DIR).unwrap();
}
pub fn action_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
.subcommand(
@@ -62,6 +49,7 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
}
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ActionInput {
#[serde(default)]
@@ -98,6 +86,7 @@ pub async fn get_action_input(
#[derive(Debug, Serialize, Deserialize, TS)]
#[serde(tag = "version")]
#[ts(export)]
pub enum ActionResult {
#[serde(rename = "0")]
V0(ActionResultV0),

View File

@@ -70,6 +70,7 @@ pub async fn write_shadow(password: &str) -> Result<(), Error> {
#[derive(Clone, Serialize, Deserialize, TS)]
#[serde(untagged)]
#[ts(export)]
pub enum PasswordType {
EncryptedWire(EncryptedWire),
String(String),
@@ -148,6 +149,14 @@ where
.no_display()
.with_about("Reset password"),
)
.subcommand(
"get-pubkey",
from_fn_async(get_pubkey)
.with_metadata("authenticated", Value::Bool(false))
.no_display()
.with_about("Get public key derived from server private key")
.with_call_remote::<CliContext>(),
)
}
#[test]
@@ -207,6 +216,7 @@ pub fn check_password(hash: &str, password: &str) -> Result<(), Error> {
#[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct LoginParams {
password: String,
#[ts(skip)]
@@ -284,6 +294,7 @@ pub async fn logout<C: AuthContext>(
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Session {
#[ts(type = "string")]
pub logged_in: DateTime<Utc>,
@@ -294,6 +305,7 @@ pub struct Session {
#[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SessionList {
#[ts(type = "string | null")]
current: Option<InternedString>,
@@ -383,7 +395,7 @@ pub async fn list<C: AuthContext>(
})
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[derive(Debug, Clone, Serialize, Deserialize)]
struct KillSessionId(InternedString);
impl KillSessionId {

View File

@@ -36,7 +36,7 @@ impl Map for CifsTargets {
}
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CifsBackupTarget {
hostname: String,

View File

@@ -34,11 +34,11 @@ use crate::util::serde::{
pub mod cifs;
#[derive(Debug, Deserialize, Serialize, TS)]
#[derive(Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
#[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")]
pub enum BackupTarget {
#[serde(rename_all = "camelCase")]
Disk {
vendor: Option<String>,
model: Option<String>,
@@ -210,21 +210,19 @@ pub async fn list(ctx: RpcContext) -> Result<BTreeMap<BackupTargetId, BackupTarg
.collect())
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BackupInfo {
#[ts(type = "string")]
pub version: Version,
pub timestamp: Option<DateTime<Utc>>,
pub package_backups: BTreeMap<PackageId, PackageBackupInfo>,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PackageBackupInfo {
pub title: InternedString,
pub version: VersionString,
#[ts(type = "string")]
pub os_version: Version,
pub timestamp: DateTime<Utc>,
}

View File

@@ -22,7 +22,7 @@ use crate::tunnel::tunnel_router;
use crate::tunnel::web::TunnelCertHandler;
use crate::util::logger::LOGGER;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum WebserverListener {
Http,
Https(SocketAddr),

View File

@@ -40,6 +40,7 @@ lazy_static::lazy_static! {
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetupResult {
pub tor_addresses: Vec<String>,
#[ts(type = "string")]

View File

@@ -1,6 +1,7 @@
pub mod model;
pub mod prelude;
use std::panic::UnwindSafe;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
@@ -55,18 +56,9 @@ pub fn db<C: Context>() -> ParentHandler<C> {
"dump",
from_fn_async(cli_dump)
.with_display_serializable()
.no_ts()
.with_about("Filter/query db to display tables and records"),
)
.subcommand(
"dump",
from_fn_async(dump)
.custom_ts(
DumpParams::inline_flattened(),
format!("{{ id: number; value: unknown }}"),
)
.no_cli(),
)
.subcommand("dump", from_fn_async(dump).no_cli())
.subcommand(
"subscribe",
from_fn_async(subscribe)
@@ -81,7 +73,6 @@ pub fn db<C: Context>() -> ParentHandler<C> {
"apply",
from_fn_async(cli_apply)
.no_display()
.no_ts()
.with_about("Update a db record"),
)
.subcommand("apply", from_fn_async(apply).no_cli())

View File

@@ -20,6 +20,7 @@ use crate::status::MainStatus;
use crate::util::serde::{Pem, is_partial_of};
#[derive(Debug, Default, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct AllPackageData(pub BTreeMap<PackageId, PackageDataEntry>);
impl Map for AllPackageData {
type Key = PackageId;
@@ -42,6 +43,7 @@ pub enum ManifestPreference {
#[serde(rename_all = "camelCase")]
#[serde(tag = "state")]
#[model = "Model<Self>"]
#[ts(export)]
pub enum PackageState {
Installing(InstallingState),
Restoring(InstallingState),
@@ -275,6 +277,7 @@ impl Model<PackageState> {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct InstallingState {
pub installing_info: InstallingInfo,
}
@@ -282,6 +285,7 @@ pub struct InstallingState {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct UpdatingState {
pub manifest: Manifest,
pub s9pk: PathBuf,
@@ -291,6 +295,7 @@ pub struct UpdatingState {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct InstalledState {
pub manifest: Manifest,
}
@@ -298,11 +303,13 @@ pub struct InstalledState {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct InstallingInfo {
pub new_manifest: Manifest,
pub progress: FullProgress,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")]
pub enum AllowedStatuses {
OnlyRunning,
@@ -337,6 +344,7 @@ pub struct ActionMetadata {
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")]
#[serde(rename_all_fields = "camelCase")]
pub enum ActionVisibility {
@@ -353,6 +361,7 @@ impl Default for ActionVisibility {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct PackageDataEntry {
pub state_info: PackageState,
pub s9pk: PathBuf,
@@ -379,6 +388,7 @@ impl AsRef<PackageDataEntry> for PackageDataEntry {
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct CurrentDependencies(pub BTreeMap<PackageId, CurrentDependencyInfo>);
impl CurrentDependencies {
pub fn map(
@@ -430,6 +440,7 @@ pub enum CurrentDependencyKind {
#[derive(Clone, Debug, Deserialize, Serialize, TS, HasModel)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
#[model = "Model<Self>"]
pub struct TaskEntry {
pub task: Task,
@@ -438,6 +449,7 @@ pub struct TaskEntry {
#[derive(Clone, Debug, Deserialize, Serialize, TS, HasModel)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
#[model = "Model<Self>"]
pub struct Task {
pub package_id: PackageId,
@@ -454,6 +466,7 @@ pub struct Task {
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "kebab-case")]
#[ts(export)]
pub enum TaskSeverity {
Optional,
Important,
@@ -467,6 +480,7 @@ impl Default for TaskSeverity {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct TaskTrigger {
#[serde(default)]
pub once: bool,
@@ -475,6 +489,7 @@ pub struct TaskTrigger {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "kebab-case")]
#[ts(export)]
pub enum TaskCondition {
InputNotMatches,
}

View File

@@ -16,12 +16,12 @@ use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::account::AccountInfo;
use crate::db::model::package::AllPackageData;
use crate::db::model::Database;
use crate::db::DbAccessByKey;
use crate::db::model::Database;
use crate::db::model::package::AllPackageData;
use crate::net::acme::AcmeProvider;
use crate::net::host::binding::{AddSslOptions, BindInfo, BindOptions, NetInfo};
use crate::net::host::Host;
use crate::net::host::binding::{AddSslOptions, BindInfo, BindOptions, NetInfo};
use crate::net::utils::ipv6_is_local;
use crate::net::vhost::AlpnInfo;
use crate::prelude::*;
@@ -33,14 +33,10 @@ use crate::util::serde::MaybeUtf8String;
use crate::version::{Current, VersionT};
use crate::{ARCH, PLATFORM};
#[test]
fn export_bindings_database() {
Public::export_all_to("./bindings/database/startos").unwrap();
}
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct Public {
pub server_info: ServerInfo,
pub package_data: AllPackageData,
@@ -156,6 +152,7 @@ fn get_platform() -> InternedString {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct ServerInfo {
#[serde(default = "get_arch")]
#[ts(type = "string")]
@@ -197,6 +194,7 @@ pub struct ServerInfo {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct NetworkInfo {
pub wifi: WifiInfo,
pub host: Host,
@@ -212,6 +210,7 @@ pub struct NetworkInfo {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct DnsSettings {
#[ts(type = "string[]")]
pub dhcp_servers: VecDeque<SocketAddr>,
@@ -222,6 +221,7 @@ pub struct DnsSettings {
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct NetworkInterfaceInfo {
pub name: Option<InternedString>,
pub public: Option<bool>,
@@ -260,15 +260,12 @@ impl NetworkInterfaceInfo {
}
pub fn secure(&self) -> bool {
self.secure.unwrap_or_else(|| {
self.ip_info.as_ref().map_or(false, |ip_info| {
ip_info.device_type == Some(NetworkInterfaceType::Wireguard)
}) && !self.public()
})
self.secure.unwrap_or(false)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize, TS, HasModel)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
pub struct IpInfo {
@@ -288,6 +285,7 @@ pub struct IpInfo {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")]
pub enum NetworkInterfaceType {
Ethernet,
@@ -300,6 +298,7 @@ pub enum NetworkInterfaceType {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct AcmeSettings {
pub contact: Vec<String>,
}
@@ -320,12 +319,14 @@ impl DbAccessByKey<AcmeSettings> for Database {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct DomainSettings {
pub gateway: GatewayId,
}
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[model = "Model<Self>"]
#[ts(export)]
pub struct BackupProgress {
pub complete: bool,
}
@@ -333,6 +334,7 @@ pub struct BackupProgress {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct ServerStatus {
pub backup_progress: Option<BTreeMap<PackageId, BackupProgress>>,
pub updated: bool,
@@ -346,6 +348,7 @@ pub struct ServerStatus {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct WifiInfo {
pub enabled: bool,
pub interface: Option<String>,
@@ -357,6 +360,7 @@ pub struct WifiInfo {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ServerSpecs {
pub cpu: String,
pub disk: String,

View File

@@ -10,7 +10,6 @@ use patch_db::value::InternedString;
pub use patch_db::{HasModel, MutateResult, PatchDb};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::prelude::*;
@@ -480,24 +479,6 @@ impl<'de, T: DeserializeOwned> Deserialize<'de> for JsonKey<T> {
))
}
}
impl<T> TS for JsonKey<T> {
type WithoutGenerics = JsonKey<ts_rs::Dummy>;
fn decl() -> String {
format!("type {} = string", Self::name())
}
fn decl_concrete() -> String {
Self::decl()
}
fn name() -> String {
"JsonKey".into()
}
fn inline() -> String {
"string".into()
}
fn inline_flattened() -> String {
Self::inline()
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct WithTimeData<T> {

View File

@@ -6,23 +6,13 @@ use models::PackageId;
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::Error;
use crate::prelude::*;
use crate::util::PathOrUrl;
use crate::Error;
#[test]
fn export_bindings_dependencies() {
use crate::service::effects::dependency::{CheckDependenciesResult, DependencyRequirement};
const OUT_DIR: &str = "./bindings/dependencies";
PackageId::export_all_to(OUT_DIR).unwrap();
DependencyRequirement::export_all_to(OUT_DIR).unwrap();
CheckDependenciesResult::export_all_to(OUT_DIR).unwrap();
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[model = "Model<Self>"]
#[ts(export)]
pub struct Dependencies(pub BTreeMap<PackageId, DepInfo>);
impl Map for Dependencies {
type Key = PackageId;
@@ -47,7 +37,7 @@ pub struct DepInfo {
impl TS for DepInfo {
type WithoutGenerics = Self;
fn decl() -> String {
format!("type {} = {}", Self::name(), Self::inline_flattened())
format!("type {} = {}", Self::name(), Self::inline())
}
fn decl_concrete() -> String {
Self::decl()
@@ -74,6 +64,7 @@ impl TS for DepInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum MetadataSrc {
Metadata(Metadata),
S9pk(Option<PathOrUrl>), // backwards compatibility
@@ -81,6 +72,7 @@ pub enum MetadataSrc {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Metadata {
pub title: InternedString,
pub icon: PathOrUrl,

View File

@@ -2,7 +2,7 @@ use std::sync::Arc;
use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{
from_fn, from_fn_async, CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler,
CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn, from_fn_async,
};
use crate::context::{CliContext, DiagnosticContext, RpcContext};
@@ -17,7 +17,6 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
.subcommand(
"error",
from_fn(error)
.unknown_ts() // TODO: TS
.with_about("Display diagnostic error")
.with_call_remote::<CliContext>(),
)
@@ -29,7 +28,6 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
"logs",
from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>)
.no_display()
.no_ts()
.with_about("Display OS logs"),
)
.subcommand(
@@ -40,7 +38,6 @@ pub fn diagnostic<C: Context>() -> ParentHandler<C> {
"kernel-logs",
from_fn_async(crate::logs::cli_logs::<DiagnosticContext, Empty>)
.no_display()
.no_ts()
.with_about("Display kernal logs"),
)
.subcommand(

View File

@@ -2,7 +2,6 @@ use std::path::Path;
use color_eyre::eyre::eyre;
use tokio::process::Command;
use ts_rs::TS;
use crate::Error;
use crate::disk::fsck::btrfs::{btrfs_check_readonly, btrfs_check_repair};
@@ -12,7 +11,7 @@ use crate::util::Invoke;
pub mod btrfs;
pub mod ext4;
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS)]
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
#[must_use]
pub struct RequiresReboot(pub bool);
impl std::ops::BitOrAssign for RequiresReboot {

View File

@@ -12,6 +12,7 @@ use crate::prelude::*;
use crate::util::io::create_file;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "kebab-case")]
pub enum FileType {
File,

View File

@@ -48,7 +48,6 @@ pub async fn bind<P0: AsRef<Path>, P1: AsRef<Path>>(
pub async fn unmount<P: AsRef<Path>>(mountpoint: P, lazy: bool) -> Result<(), Error> {
tracing::debug!("Unmounting {}.", mountpoint.as_ref().display());
let mut cmd = tokio::process::Command::new("umount");
cmd.arg("-R");
if lazy {
cmd.arg("-l");
}

View File

@@ -13,7 +13,6 @@ use regex::Regex;
use serde::{Deserialize, Serialize};
use tokio::process::Command;
use tracing::instrument;
use ts_rs::TS;
use super::mount::filesystem::ReadOnly;
use super::mount::filesystem::block_dev::BlockDev;
@@ -25,14 +24,14 @@ use crate::util::Invoke;
use crate::util::serde::IoFormat;
use crate::{Error, ResultExt as _};
#[derive(Clone, Copy, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "kebab-case")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum PartitionTable {
Mbr,
Gpt,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DiskInfo {
pub logicalname: PathBuf,
@@ -44,7 +43,7 @@ pub struct DiskInfo {
pub guid: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PartitionInfo {
pub logicalname: PathBuf,
@@ -55,11 +54,10 @@ pub struct PartitionInfo {
pub guid: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StartOsRecoveryInfo {
pub hostname: Hostname,
#[ts(type = "string")]
pub version: exver::Version,
pub timestamp: DateTime<Utc>,
pub password_hash: Option<String>,
@@ -282,6 +280,9 @@ pub async fn list(os: &OsPartitionInfo) -> Result<Vec<DiskInfo>, Error> {
.try_fold(
BTreeMap::<PathBuf, DiskIndex>::new(),
|mut disks, dir_entry| async move {
if dir_entry.file_type().await?.is_dir() {
return Ok(disks);
}
if let Some(disk_path) = dir_entry.path().file_name().and_then(|s| s.to_str()) {
let (disk_path, part_path) = if let Some(end) = PARTITION_REGEX.find(disk_path) {
(

View File

@@ -1,14 +1,12 @@
use imbl_value::InternedString;
use lazy_format::lazy_format;
use rand::{Rng, rng};
use serde::{Deserialize, Serialize};
use tokio::process::Command;
use tracing::instrument;
use ts_rs::TS;
use crate::util::Invoke;
use crate::{Error, ErrorKind};
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
pub struct Hostname(pub InternedString);
lazy_static::lazy_static! {

View File

@@ -8,7 +8,7 @@ use const_format::formatcp;
use futures::{StreamExt, TryStreamExt};
use itertools::Itertools;
use models::ResultExt;
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerArgs, HandlerExt, ParentHandler};
use rpc_toolkit::{Context, Empty, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize};
use tokio::process::Command;
use tracing::instrument;
@@ -17,8 +17,8 @@ use ts_rs::TS;
use crate::account::AccountInfo;
use crate::context::config::ServerConfig;
use crate::context::{CliContext, InitContext, RpcContext};
use crate::db::model::public::ServerStatus;
use crate::db::model::Database;
use crate::db::model::public::ServerStatus;
use crate::developer::OS_DEVELOPER_KEY_PATH;
use crate::hostname::Hostname;
use crate::middleware::auth::AuthContext;
@@ -35,10 +35,10 @@ use crate::rpc_continuations::{Guid, RpcContinuation};
use crate::s9pk::v2::pack::{CONTAINER_DATADIR, CONTAINER_TOOL};
use crate::ssh::SSH_DIR;
use crate::system::{get_mem_info, sync_kiosk};
use crate::util::io::{open_file, IOHook};
use crate::util::io::{IOHook, open_file};
use crate::util::lshw::lshw;
use crate::util::net::WebSocketExt;
use crate::util::{cpupower, Invoke};
use crate::util::{Invoke, cpupower};
use crate::{Error, MAIN_DATA, PACKAGE_DATA};
pub const SYSTEM_REBUILD_PATH: &str = "/media/startos/config/system-rebuild";
@@ -425,7 +425,6 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
"logs",
from_fn_async(crate::logs::cli_logs::<InitContext, Empty>)
.no_display()
.no_ts()
.with_about("Display OS logs"),
)
.subcommand(
@@ -436,7 +435,6 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
"kernel-logs",
from_fn_async(crate::logs::cli_logs::<InitContext, Empty>)
.no_display()
.no_ts()
.with_about("Display kernel logs"),
)
.subcommand("subscribe", from_fn_async(init_progress).no_cli())
@@ -450,6 +448,7 @@ pub fn init_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct InitProgressRes {
pub progress: FullProgress,
pub guid: Guid,

View File

@@ -112,6 +112,7 @@ impl std::fmt::Display for MinMax {
#[derive(Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct InstallParams {
#[ts(type = "string")]
registry: Url,
@@ -353,6 +354,7 @@ impl FromArgMatches for CliInstallParams {
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[ts(export)]
pub struct InstalledVersionParams {
id: PackageId,
}

View File

@@ -79,8 +79,8 @@ pub use error::{Error, ErrorKind, ResultExt};
use imbl_value::Value;
use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{
from_fn, from_fn_async, from_fn_async_local, from_fn_blocking, CallRemoteHandler, Context,
Empty, HandlerExt, ParentHandler,
CallRemoteHandler, Context, Empty, HandlerExt, ParentHandler, from_fn, from_fn_async,
from_fn_async_local, from_fn_blocking,
};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
@@ -90,11 +90,12 @@ use crate::disk::fsck::RequiresReboot;
use crate::registry::context::{RegistryContext, RegistryUrlParams};
use crate::system::kiosk;
use crate::tunnel::context::TunnelUrlParams;
use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat};
use crate::util::serde::{HandlerExtSerde, WithIoFormat, display_serializable};
#[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct EchoParams {
message: String,
}
@@ -105,6 +106,7 @@ pub fn echo<C: Context>(_: C, EchoParams { message }: EchoParams) -> Result<Stri
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum ApiState {
Error,
Initializing,
@@ -116,70 +118,6 @@ impl std::fmt::Display for ApiState {
}
}
#[test]
fn export_bindings_api_helper() {
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/api-helpers.ts",
rpc_toolkit::type_helpers().as_bytes(),
)
.unwrap();
}
#[test]
fn export_bindings_main_apis() {
use rpc_toolkit::HandlerTS;
use crate::context::{InstallContext, SetupContext};
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/main-api.ts",
format!(
"export type MainApi = {}",
main_api::<RpcContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/init-api.ts",
format!(
"export type InitApi = {}",
main_api::<InitContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/diagnostic-api.ts",
format!(
"export type DiagnosticApi = {}",
main_api::<DiagnosticContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/setup-api.ts",
format!(
"export type SetupApi = {}",
main_api::<SetupContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
std::fs::write(
"./bindings/os-install-api.ts",
format!(
"export type OsInstallApi = {}",
main_api::<InstallContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
}
pub fn main_api<C: Context>() -> ParentHandler<C> {
let mut api = ParentHandler::new()
.subcommand(
@@ -339,7 +277,7 @@ pub fn server<C: Context>() -> ParentHandler<C> {
)
.subcommand(
"logs",
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().no_ts().with_about("Display OS logs"),
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().with_about("Display OS logs"),
)
.subcommand(
"kernel-logs",
@@ -347,7 +285,7 @@ pub fn server<C: Context>() -> ParentHandler<C> {
)
.subcommand(
"kernel-logs",
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().no_ts().with_about("Display Kernel logs"),
from_fn_async(logs::cli_logs::<RpcContext, Empty>).no_display().with_about("Display Kernel logs"),
)
.subcommand(
"metrics",
@@ -359,7 +297,7 @@ pub fn server<C: Context>() -> ParentHandler<C> {
.with_call_remote::<CliContext>()
)
.subcommand(
"follow",
"follow",
from_fn_async(system::metrics_follow)
.no_cli()
)
@@ -456,7 +394,6 @@ pub fn package<C: Context>() -> ParentHandler<C> {
"install",
from_fn_async_local(install::cli_install)
.no_display()
.no_ts()
.with_about("Install a package from a marketplace or via sideloading"),
)
.subcommand(
@@ -560,6 +497,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
.with_about("List information related to the lxc containers i.e. CPU, Memory, Disk")
.with_call_remote::<CliContext>(),
)
.subcommand("logs", logs::package_logs())
.subcommand(
"logs",
logs::package_logs().with_about("Display package logs"),
@@ -568,7 +506,6 @@ pub fn package<C: Context>() -> ParentHandler<C> {
"logs",
from_fn_async(logs::cli_logs::<RpcContext, logs::PackageIdParams>)
.no_display()
.no_ts()
.with_about("Display package logs"),
)
.subcommand(
@@ -583,16 +520,7 @@ pub fn package<C: Context>() -> ParentHandler<C> {
.with_about("Execute commands within a service container")
.no_cli(),
)
.subcommand(
"attach",
from_fn_async(service::cli_attach).no_display().no_ts(),
)
.subcommand(
"list-subcontainers",
from_fn_async(service::list_subcontainers)
.with_about("List all subcontainers for a package")
.no_cli(),
)
.subcommand("attach", from_fn_async(service::cli_attach).no_display())
.subcommand(
"host",
net::host::host_api::<C>().with_about("Manage network hosts for a package"),

View File

@@ -15,8 +15,7 @@ use itertools::Itertools;
use models::{FromStrParser, PackageId};
use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::{
from_fn_async, CallRemote, Context, Empty, HandlerArgs, HandlerExt, HandlerFor, LeafHandler,
ParentHandler, UnknownTS,
CallRemote, Context, Empty, HandlerArgs, HandlerExt, HandlerFor, ParentHandler, from_fn_async,
};
use serde::de::{self, DeserializeOwned};
use serde::{Deserialize, Serialize};
@@ -25,16 +24,15 @@ use tokio::process::{Child, Command};
use tokio_stream::wrappers::LinesStream;
use tokio_tungstenite::tungstenite::Message;
use tracing::instrument;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext};
use crate::error::ResultExt;
use crate::lxc::ContainerId;
use crate::prelude::*;
use crate::rpc_continuations::{Guid, RpcContinuation, RpcContinuations};
use crate::util::Invoke;
use crate::util::net::WebSocketExt;
use crate::util::serde::Reversible;
use crate::util::Invoke;
#[pin_project::pin_project]
pub struct LogStream {
@@ -111,21 +109,21 @@ async fn ws_handler(
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, TS)]
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct LogResponse {
pub entries: Reversible<LogEntry>,
start_cursor: Option<String>,
end_cursor: Option<String>,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, TS)]
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct LogFollowResponse {
start_cursor: Option<String>,
guid: Guid,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, TS)]
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct LogEntry {
timestamp: DateTime<Utc>,
@@ -144,7 +142,7 @@ impl std::fmt::Display for LogEntry {
}
}
#[derive(Serialize, Deserialize, Debug, TS)]
#[derive(Serialize, Deserialize, Debug)]
pub struct JournalctlEntry {
#[serde(rename = "__REALTIME_TIMESTAMP")]
pub timestamp: String,
@@ -230,15 +228,14 @@ pub enum LogSource {
pub const SYSTEM_UNIT: &str = "startd";
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
#[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")]
pub struct PackageIdParams {
id: PackageId,
}
#[derive(Debug, Clone, TS)]
#[ts(type = "number | string")]
#[derive(Debug, Clone)]
pub enum BootIdentifier {
Index(i32),
Id(String),
@@ -341,11 +338,6 @@ pub struct LogsParams<Extra: FromArgMatches + Args = Empty> {
#[serde(default)]
before: bool,
}
impl<Extra: FromArgMatches + Args + TS> LogsParams<Extra> {
pub fn inline_ty() -> String {
format!("{} & {{ limit: number | null; cursor: string | null; boot: string | number | null; before: boolean }}", Extra::inline_flattened())
}
}
#[derive(Deserialize, Serialize, Parser)]
#[serde(rename_all = "camelCase")]
@@ -362,30 +354,18 @@ pub struct CliLogsParams<Extra: FromArgMatches + Args = Empty> {
#[allow(private_bounds)]
pub fn logs<
C: Context + AsRef<RpcContinuations>,
Extra: FromArgMatches + Serialize + DeserializeOwned + Args + TS + Send + Sync + 'static,
Extra: FromArgMatches + Serialize + DeserializeOwned + Args + Send + Sync + 'static,
>(
source: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> UnknownTS<ParentHandler<C, LogsParams<Extra>>> {
) -> ParentHandler<C, LogsParams<Extra>> {
ParentHandler::new()
.root_handler(
logs_nofollow::<C, Extra>(source.clone())
.no_cli()
.custom_ts(
LogsParams::<Extra>::inline_ty(),
LogResponse::inline_flattened(),
),
)
.root_handler(logs_nofollow::<C, Extra>(source.clone()).no_cli())
.subcommand(
"follow",
logs_follow::<C, Extra>(source)
.with_inherited(|params, _| params)
.no_cli()
.custom_ts(
LogsParams::<Extra>::inline_ty(),
LogFollowResponse::inline_flattened(),
),
.no_cli(),
)
.unknown_ts()
}
pub async fn cli_logs<RemoteContext, Extra>(
@@ -399,7 +379,7 @@ pub async fn cli_logs<RemoteContext, Extra>(
) -> Result<(), RpcError>
where
CliContext: CallRemote<RemoteContext>,
Extra: FromArgMatches + Args + TS + Serialize + Send + Sync,
Extra: FromArgMatches + Args + Serialize + Send + Sync,
{
let method = parent_method
.into_iter()
@@ -451,16 +431,10 @@ where
fn logs_nofollow<C, Extra>(
f: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> impl HandlerFor<
C,
Params = LogsParams<Extra>,
InheritedParams = Empty,
Ok = LogResponse,
Err = Error,
> + LeafHandler
) -> impl HandlerFor<C, Params = LogsParams<Extra>, InheritedParams = Empty, Ok = LogResponse, Err = Error>
where
C: Context,
Extra: FromArgMatches + Args + TS + Send + Sync + 'static,
Extra: FromArgMatches + Args + Send + Sync + 'static,
{
from_fn_async(
move |HandlerArgs {
@@ -492,7 +466,7 @@ where
fn logs_follow<
C: Context + AsRef<RpcContinuations>,
Extra: FromArgMatches + Args + TS + Send + Sync + 'static,
Extra: FromArgMatches + Args + Send + Sync + 'static,
>(
f: impl for<'a> LogSourceFn<'a, C, Extra>,
) -> impl HandlerFor<
@@ -501,7 +475,7 @@ fn logs_follow<
InheritedParams = LogsParams<Extra>,
Ok = LogFollowResponse,
Err = Error,
> + LeafHandler {
> {
from_fn_async(
move |HandlerArgs {
context,
@@ -543,7 +517,7 @@ async fn get_package_id(
Ok(LogSource::Container(container_id))
}
pub fn package_logs() -> UnknownTS<ParentHandler<RpcContext, LogsParams<PackageIdParams>>> {
pub fn package_logs() -> ParentHandler<RpcContext, LogsParams<PackageIdParams>> {
logs::<RpcContext, PackageIdParams>(get_package_id)
}

View File

@@ -366,6 +366,7 @@ impl LxcContainer {
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
tracing::info!("Connected to socket in {:?}", started.elapsed());
Ok(UnixRpcClient::new(sock_path))
}
}

View File

@@ -24,7 +24,6 @@ use sha2::Sha256;
use tokio::io::AsyncWriteExt;
use tokio::process::Command;
use tokio::sync::Mutex;
use ts_rs::TS;
use crate::auth::{Sessions, check_password, write_shadow};
use crate::context::RpcContext;
@@ -90,7 +89,7 @@ impl AuthContext for RpcContext {
}
}
#[derive(Deserialize, Serialize, TS)]
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct LoginRes {
pub session: InternedString,
@@ -101,7 +100,7 @@ pub trait AsLogoutSessionId {
}
/// Will need to know when we have logged out from a route
#[derive(Serialize, Deserialize, TS)]
#[derive(Serialize, Deserialize)]
pub struct HasLoggedOutSessions(());
impl HasLoggedOutSessions {

View File

@@ -460,7 +460,7 @@ impl ValueParserFactory for AcmeProvider {
}
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct InitAcmeParams {
#[arg(long)]
pub provider: AcmeProvider,
@@ -485,7 +485,7 @@ pub async fn init(
Ok(())
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct RemoveAcmeParams {
#[arg(long)]
pub provider: AcmeProvider,

View File

@@ -32,7 +32,6 @@ use rpc_toolkit::{
use serde::{Deserialize, Serialize};
use tokio::net::{TcpListener, UdpSocket};
use tracing::instrument;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext};
use crate::db::model::Database;
@@ -100,7 +99,7 @@ pub fn dns_api<C: Context>() -> ParentHandler<C> {
)
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct QueryDnsParams {
pub fqdn: InternedString,
}
@@ -139,7 +138,7 @@ pub fn query_dns<C: Context>(
.map_err(Error::from)
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct SetStaticDnsParams {
pub servers: Option<Vec<String>>,
}

View File

@@ -13,7 +13,6 @@ use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async
use serde::{Deserialize, Serialize};
use tokio::process::Command;
use tokio::sync::mpsc;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext};
use crate::db::model::public::NetworkInterfaceInfo;
@@ -438,7 +437,8 @@ impl InterfaceForwardState {
for mut entry in self.state.iter_mut() {
entry.gc(ip_info, &self.port_forward).await?;
}
Ok(())
self.port_forward.gc().await
}
}
@@ -449,10 +449,10 @@ fn err_has_exited<T>(_: T) -> Error {
)
}
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForwardTable(pub BTreeMap<u16, ForwardTarget>);
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ForwardTarget {
pub target: SocketAddrV4,
pub filter: String,
@@ -538,7 +538,6 @@ impl InterfacePortForwardController {
_ = ip_info.changed() => {
interfaces = ip_info.read();
state.sync(&interfaces).await.log_err();
state.port_forward.gc().await.log_err();
}
}
}

View File

@@ -1,9 +1,10 @@
use std::any::Any;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt;
use std::future::Future;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV6};
use std::sync::{Arc, Weak};
use std::task::{ready, Poll};
use std::task::{Poll, ready};
use std::time::Duration;
use clap::Parser;
@@ -17,7 +18,7 @@ use itertools::Itertools;
use models::GatewayId;
use nix::net::if_::if_nametoindex;
use patch_db::json_ptr::JsonPointer;
use rpc_toolkit::{from_fn_async, Context, HandlerArgs, HandlerExt, ParentHandler};
use rpc_toolkit::{Context, HandlerArgs, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize};
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::net::TcpListener;
@@ -29,29 +30,28 @@ use zbus::proxy::{PropertyChanged, PropertyStream, SignalStream};
use zbus::zvariant::{
DeserializeDict, Dict, OwnedObjectPath, OwnedValue, Type as ZType, Value as ZValue,
};
use zbus::{proxy, Connection};
use zbus::{Connection, proxy};
use crate::context::{CliContext, RpcContext};
use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType};
use crate::db::model::Database;
use crate::db::model::public::{IpInfo, NetworkInterfaceInfo, NetworkInterfaceType};
use crate::net::forward::START9_BRIDGE_IFACE;
use crate::net::gateway::device::DeviceProxy;
use crate::net::utils::ipv6_is_link_local;
use crate::net::web_server::{Accept, AcceptStream, Acceptor, MetadataVisitor};
use crate::prelude::*;
use crate::util::Invoke;
use crate::util::collections::OrdMapIterMut;
use crate::util::future::Until;
use crate::util::io::open_file;
use crate::util::serde::{display_serializable, HandlerExtSerde};
use crate::util::serde::{HandlerExtSerde, display_serializable};
use crate::util::sync::{SyncMutex, Watch};
use crate::util::Invoke;
pub fn gateway_api<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
.subcommand(
"list",
from_fn_async(list_interfaces)
.custom_ts("{}".into(), BTreeMap::<GatewayId, NetworkInterfaceInfo>::inline_flattened())
.with_display_serializable()
.with_custom_display_fn(|HandlerArgs { params, .. }, res| {
use prettytable::*;
@@ -438,60 +438,54 @@ async fn watcher(
loop {
until
.run(async {
loop {
let devices = netman_proxy.all_devices().await?;
if devices.is_empty() {
tracing::warn!(
"NetworkManager returned no devices. Trying again..."
);
tokio::time::sleep(Duration::from_secs(1)).await;
let devices = netman_proxy.all_devices().await?;
ensure_code!(
!devices.is_empty(),
ErrorKind::Network,
"NetworkManager returned no devices. Trying again..."
);
let mut ifaces = BTreeSet::new();
let mut jobs = Vec::new();
for device in devices {
use futures::future::Either;
let device_proxy =
device::DeviceProxy::new(&connection, device.clone()).await?;
let iface = InternedString::intern(device_proxy.ip_interface().await?);
if iface.is_empty() {
continue;
}
let mut ifaces = BTreeSet::new();
let mut jobs = Vec::new();
for device in devices {
use futures::future::Either;
let device_proxy =
device::DeviceProxy::new(&connection, device.clone()).await?;
let iface =
InternedString::intern(device_proxy.ip_interface().await?);
if iface.is_empty() {
continue;
}
let iface: GatewayId = iface.into();
if watch_activation.peek(|a| a.contains_key(&iface)) {
jobs.push(Either::Left(watch_activated(
&connection,
device_proxy.clone(),
iface.clone(),
&watch_activation,
)));
}
jobs.push(Either::Right(watch_ip(
let iface: GatewayId = iface.into();
if watch_activation.peek(|a| a.contains_key(&iface)) {
jobs.push(Either::Left(watch_activated(
&connection,
device_proxy.clone(),
iface.clone(),
&watch_ip_info,
&watch_activation,
)));
ifaces.insert(iface);
}
watch_ip_info.send_if_modified(|m| {
let mut changed = false;
for (iface, info) in OrdMapIterMut::from(m) {
if !ifaces.contains(iface) {
info.ip_info = None;
changed = true;
}
}
changed
});
futures::future::try_join_all(jobs).await?;
break;
jobs.push(Either::Right(watch_ip(
&connection,
device_proxy.clone(),
iface.clone(),
&watch_ip_info,
)));
ifaces.insert(iface);
}
watch_ip_info.send_if_modified(|m| {
let mut changed = false;
for (iface, info) in OrdMapIterMut::from(m) {
if !ifaces.contains(iface) {
info.ip_info = None;
changed = true;
}
}
changed
});
futures::future::try_join_all(jobs).await?;
Ok::<_, Error>(())
})
.await?;
@@ -1552,6 +1546,14 @@ pub struct NetworkInterfaceListenerAcceptMetadata<B: Bind> {
pub inner: <B::Accept as Accept>::Metadata,
pub info: GatewayInfo,
}
impl<B: Bind> fmt::Debug for NetworkInterfaceListenerAcceptMetadata<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NetworkInterfaceListenerAcceptMetadata")
.field("inner", &self.inner)
.field("info", &self.info)
.finish()
}
}
impl<B: Bind> Clone for NetworkInterfaceListenerAcceptMetadata<B>
where
<B::Accept as Accept>::Metadata: Clone,
@@ -1628,3 +1630,39 @@ where
Self::new(Some(Either::Left(listener)))
}
}
#[test]
fn test_filter() {
use crate::net::host::binding::NetInfo;
let wg1 = "wg1".parse::<GatewayId>().unwrap();
assert!(!InterfaceFilter::filter(
&AndFilter(
NetInfo {
private_disabled: [wg1.clone()].into_iter().collect(),
public_enabled: Default::default(),
assigned_port: None,
assigned_ssl_port: None,
},
AndFilter(IdFilter(wg1.clone()), PublicFilter { public: false }),
)
.into_dyn(),
&wg1,
&NetworkInterfaceInfo {
name: None,
public: None,
secure: None,
ip_info: Some(Arc::new(IpInfo {
name: "".into(),
scope_id: 3,
device_type: Some(NetworkInterfaceType::Wireguard),
subnets: ["10.59.0.2/24".parse::<IpNet>().unwrap()]
.into_iter()
.collect(),
lan_ip: Default::default(),
wan_ip: None,
ntp_servers: Default::default(),
dns_servers: Default::default(),
})),
},
));
}

View File

@@ -16,7 +16,7 @@ use crate::net::tor::OnionAddress;
use crate::prelude::*;
use crate::util::serde::{HandlerExtSerde, display_serializable};
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "kebab-case")]
#[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")]
@@ -235,7 +235,7 @@ pub fn address_api<C: Context, Kind: HostApiKind>()
)
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct AddPublicDomainParams {
pub fqdn: InternedString,
#[arg(long)]
@@ -282,7 +282,7 @@ pub async fn add_public_domain<Kind: HostApiKind>(
.with_kind(ErrorKind::Unknown)?
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct RemoveDomainParams {
pub fqdn: InternedString,
}
@@ -305,7 +305,7 @@ pub async fn remove_public_domain<Kind: HostApiKind>(
Ok(())
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct AddPrivateDomainParams {
pub fqdn: InternedString,
}
@@ -347,7 +347,7 @@ pub async fn remove_private_domain<Kind: HostApiKind>(
Ok(())
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct OnionParams {
pub onion: String,
}

View File

@@ -19,6 +19,7 @@ use crate::prelude::*;
use crate::util::serde::{HandlerExtSerde, display_serializable};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct BindId {
pub id: HostId,
@@ -45,6 +46,7 @@ impl FromStr for BindId {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindInfo {
pub enabled: bool,
pub options: BindOptions,
@@ -53,6 +55,7 @@ pub struct BindInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct NetInfo {
#[ts(as = "BTreeSet::<GatewayId>")]
#[serde(default)]
@@ -142,6 +145,7 @@ impl InterfaceFilter for NetInfo {
}
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct Security {
pub ssl: bool,
@@ -149,6 +153,7 @@ pub struct Security {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindOptions {
pub preferred_external_port: u16,
pub add_ssl: Option<AddSslOptions>,
@@ -157,6 +162,7 @@ pub struct BindOptions {
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddSslOptions {
pub preferred_external_port: u16,
// #[serde(default)]
@@ -228,6 +234,7 @@ pub async fn list_bindings<Kind: HostApiKind>(
#[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindingGatewaySetEnabledParams {
internal_port: u16,
gateway: GatewayId,

View File

@@ -25,6 +25,7 @@ pub mod binding;
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct Host {
pub bindings: BTreeMap<u16, BindInfo>,
#[ts(type = "string[]")]
@@ -73,6 +74,7 @@ impl Host {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[model = "Model<Self>"]
#[ts(export)]
pub struct Hosts(pub BTreeMap<HostId, Host>);
impl Map for Hosts {
@@ -162,12 +164,12 @@ impl Model<Host> {
}
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct RequiresPackageId {
package: PackageId,
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct RequiresHostId {
host: HostId,
}

View File

@@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
use ts_rs::TS;
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")]
@@ -29,6 +30,7 @@ impl HostnameInfo {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct GatewayInfo {
pub id: GatewayId,
@@ -37,6 +39,7 @@ pub struct GatewayInfo {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct OnionHostname {
#[ts(type = "string")]
@@ -51,6 +54,7 @@ impl OnionHostname {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
#[serde(rename_all_fields = "camelCase")]
#[serde(tag = "kind")]
@@ -92,6 +96,7 @@ impl IpHostname {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ServiceInterface {
pub id: ServiceInterfaceId,
@@ -104,6 +109,7 @@ pub struct ServiceInterface {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub enum ServiceInterfaceType {
Ui,
@@ -112,6 +118,7 @@ pub enum ServiceInterfaceType {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct AddressInfo {
pub username: Option<String>,

View File

@@ -357,7 +357,7 @@ pub fn display_services(
Ok(())
}
#[derive(Debug, Serialize, Deserialize, TS)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum OnionServiceState {
Shutdown,
@@ -383,7 +383,7 @@ impl From<ArtiOnionServiceState> for OnionServiceState {
}
}
#[derive(Debug, Serialize, Deserialize, TS)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OnionServiceInfo {
pub state: OnionServiceState,

View File

@@ -15,7 +15,7 @@ use imbl::OrdMap;
use imbl_value::InternedString;
use lazy_static::lazy_static;
use regex::Regex;
use rpc_toolkit::{from_fn_async, Context, Empty, HandlerExt, ParentHandler, UnknownTS};
use rpc_toolkit::{Context, Empty, HandlerExt, ParentHandler, from_fn_async};
use serde::{Deserialize, Serialize};
use tokio::net::TcpStream;
use tokio::process::Command;
@@ -27,16 +27,16 @@ use tracing::instrument;
use ts_rs::TS;
use crate::context::{CliContext, RpcContext};
use crate::logs::{journalctl, LogSource, LogsParams};
use crate::logs::{LogSource, LogsParams, journalctl};
use crate::prelude::*;
use crate::util::Invoke;
use crate::util::collections::ordmap_retain;
use crate::util::io::{write_file_atomic, ReadWriter};
use crate::util::io::{ReadWriter, write_file_atomic};
use crate::util::serde::{
deserialize_from_str, display_serializable, serialize_display, Base64, HandlerExtSerde,
WithIoFormat, BASE64,
BASE64, Base64, HandlerExtSerde, WithIoFormat, deserialize_from_str, display_serializable,
serialize_display,
};
use crate::util::sync::Watch;
use crate::util::Invoke;
pub const SYSTEMD_UNIT: &str = "tor@default";
const STARTING_HEALTH_TIMEOUT: u64 = 120; // 2min
@@ -45,8 +45,7 @@ const TOR_CONTROL: SocketAddr =
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 1, 1), 9051));
const TOR_SOCKS: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 1, 1), 9050));
#[derive(Debug, Clone, Copy, PartialEq, Eq, TS)]
#[ts(type = "string")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OnionAddress(OnionAddressV3);
impl std::fmt::Display for OnionAddress {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -256,7 +255,6 @@ pub fn tor_api<C: Context>() -> ParentHandler<C> {
"logs",
from_fn_async(crate::logs::cli_logs::<RpcContext, Empty>)
.no_display()
.no_ts()
.with_about("Display Tor logs"),
)
.subcommand(
@@ -314,7 +312,7 @@ pub async fn generate_key(ctx: RpcContext) -> Result<OnionAddress, Error> {
.result
}
#[derive(Deserialize, Serialize, Parser, TS)]
#[derive(Deserialize, Serialize, Parser)]
pub struct AddKeyParams {
pub key: Base64<[u8; 64]>,
}
@@ -388,7 +386,7 @@ pub async fn list_services(ctx: RpcContext, _: Empty) -> Result<Vec<OnionAddress
ctx.net_controller.tor.list_services().await
}
pub fn logs() -> UnknownTS<ParentHandler<RpcContext, LogsParams>> {
pub fn logs() -> ParentHandler<RpcContext, LogsParams> {
crate::logs::logs::<RpcContext, Empty>(|_: &RpcContext, _| async {
Ok(LogSource::Unit(SYSTEMD_UNIT))
})
@@ -651,16 +649,6 @@ async fn torctl(
.invoke(ErrorKind::Tor)
.await?;
let logs = journalctl(
LogSource::Unit(SYSTEMD_UNIT),
Some(0),
None,
Some("0"),
false,
true,
)
.await?;
let mut tcp_stream = None;
for _ in 0..60 {
if let Ok(conn) = TcpStream::connect(tor_control).await {
@@ -722,7 +710,7 @@ async fn torctl(
ErrorKind::Tor,
));
}
Ok((connection, logs))
Ok(connection)
};
let pre_handler = async {
while let Some(command) = recv.recv().await {
@@ -747,7 +735,7 @@ async fn torctl(
Ok(())
};
let (mut connection, mut logs) = tokio::select! {
let mut connection = tokio::select! {
res = bootstrap => res?,
res = pre_handler => return res,
};
@@ -853,45 +841,59 @@ async fn torctl(
Ok(())
};
let log_parser = async {
while let Some(log) = logs.try_next().await? {
for (regex, severity) in &*LOG_REGEXES {
if regex.is_match(&log.message) {
let (check, wipe_state) = match severity {
ErrorLogSeverity::Fatal { wipe_state } => (false, *wipe_state),
ErrorLogSeverity::Unknown { wipe_state } => (true, *wipe_state),
};
let addr = hck_key.public().get_onion_address().to_string();
if !check
|| TcpStream::connect(tor_socks)
.map_err(|e| Error::new(e, ErrorKind::Tor))
.and_then(|mut tor_socks| async move {
tokio::time::timeout(
Duration::from_secs(30),
socks5_impl::client::connect(&mut tor_socks, (addr, 80), None)
.map_err(|e| Error::new(e, ErrorKind::Tor)),
)
loop {
let mut logs = journalctl(
LogSource::Unit(SYSTEMD_UNIT),
Some(0),
None,
Some("0"),
false,
true,
)
.await?;
while let Some(log) = logs.try_next().await? {
for (regex, severity) in &*LOG_REGEXES {
if regex.is_match(&log.message) {
let (check, wipe_state) = match severity {
ErrorLogSeverity::Fatal { wipe_state } => (false, *wipe_state),
ErrorLogSeverity::Unknown { wipe_state } => (true, *wipe_state),
};
let addr = hck_key.public().get_onion_address().to_string();
if !check
|| TcpStream::connect(tor_socks)
.map_err(|e| Error::new(e, ErrorKind::Tor))
.await?
})
.await
.with_ctx(|_| (ErrorKind::Tor, "Tor is confirmed to be down"))
.log_err()
.is_some()
{
if wipe_state {
Command::new("systemctl")
.arg("stop")
.arg("tor")
.invoke(ErrorKind::Tor)
.await?;
tokio::fs::remove_dir_all("/var/lib/tor").await?;
.and_then(|mut tor_socks| async move {
tokio::time::timeout(
Duration::from_secs(30),
socks5_impl::client::connect(
&mut tor_socks,
(addr, 80),
None,
)
.map_err(|e| Error::new(e, ErrorKind::Tor)),
)
.map_err(|e| Error::new(e, ErrorKind::Tor))
.await?
})
.await
.with_ctx(|_| (ErrorKind::Tor, "Tor is confirmed to be down"))
.log_err()
.is_some()
{
if wipe_state {
Command::new("systemctl")
.arg("stop")
.arg("tor")
.invoke(ErrorKind::Tor)
.await?;
tokio::fs::remove_dir_all("/var/lib/tor").await?;
}
return Err(Error::new(eyre!("{}", log.message), ErrorKind::Tor));
}
return Err(Error::new(eyre!("{}", log.message), ErrorKind::Tor));
}
}
}
}
Err(Error::new(eyre!("Log stream terminated"), ErrorKind::Tor))
};
let health_checker = async {
let mut last_success = Instant::now();
@@ -961,20 +963,23 @@ impl TorControl {
_thread: tokio::spawn(async move {
let wipe_state = AtomicBool::new(false);
let mut health_timeout = Duration::from_secs(STARTING_HEALTH_TIMEOUT);
while let Err(e) = torctl(
tor_control,
tor_socks,
&mut recv,
&mut thread_services,
&wipe_state,
&mut health_timeout,
)
.await
{
tracing::error!("{e}: Restarting tor");
tracing::debug!("{e:?}");
loop {
if let Err(e) = torctl(
tor_control,
tor_socks,
&mut recv,
&mut thread_services,
&wipe_state,
&mut health_timeout,
)
.await
{
tracing::error!("TorControl : {e}");
tracing::debug!("{e:?}");
}
tracing::info!("Restarting Tor");
tokio::time::sleep(Duration::from_secs(1)).await;
}
tracing::info!("TorControl is shut down.")
})
.into(),
send,

View File

@@ -32,6 +32,7 @@ pub fn tunnel_api<C: Context>() -> ParentHandler<C> {
}
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
pub struct AddTunnelParams {
name: InternedString,
config: String,
@@ -103,6 +104,7 @@ pub async fn add_tunnel(
}
#[derive(Debug, Clone, Deserialize, Serialize, Parser, TS)]
#[ts(export)]
pub struct RemoveTunnelParams {
id: GatewayId,
}

View File

@@ -1,5 +1,6 @@
use std::any::Any;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
use std::net::{IpAddr, SocketAddr};
use std::sync::{Arc, Weak};
use std::task::{Poll, ready};
@@ -41,6 +42,7 @@ use crate::net::tls::{
use crate::net::web_server::{Accept, AcceptStream, ExtractVisitor, TcpMetadata, extract};
use crate::prelude::*;
use crate::util::collections::EqSet;
use crate::util::future::WeakFuture;
use crate::util::serde::{HandlerExtSerde, MaybeUtf8String, display_serializable};
use crate::util::sync::{SyncMutex, Watch};
@@ -186,7 +188,7 @@ pub trait VHostTarget<A: Accept>: std::fmt::Debug + Eq {
hello: &'a ClientHello<'a>,
metadata: &'a <A as Accept>::Metadata,
) -> impl Future<Output = Option<(ServerConfig, Self::PreprocessRes)>> + Send + 'a;
fn handle_stream(&self, stream: AcceptStream, prev: Self::PreprocessRes);
fn handle_stream(&self, stream: AcceptStream, prev: Self::PreprocessRes, rc: Weak<()>);
}
pub trait DynVHostTargetT<A: Accept>: std::fmt::Debug + Any {
@@ -198,7 +200,7 @@ pub trait DynVHostTargetT<A: Accept>: std::fmt::Debug + Any {
hello: &'a ClientHello<'a>,
metadata: &'a <A as Accept>::Metadata,
) -> BoxFuture<'a, Option<(ServerConfig, Box<dyn Any + Send>)>>;
fn handle_stream(&self, stream: AcceptStream, prev: Box<dyn Any + Send>);
fn handle_stream(&self, stream: AcceptStream, prev: Box<dyn Any + Send>, rc: Weak<()>);
fn eq(&self, other: &dyn DynVHostTargetT<A>) -> bool;
}
impl<A: Accept, T: VHostTarget<A> + 'static> DynVHostTargetT<A> for T {
@@ -218,9 +220,9 @@ impl<A: Accept, T: VHostTarget<A> + 'static> DynVHostTargetT<A> for T {
.map(|o| o.map(|(cfg, res)| (cfg, Box::new(res) as Box<dyn Any + Send>)))
.boxed()
}
fn handle_stream(&self, stream: AcceptStream, prev: Box<dyn Any + Send>) {
fn handle_stream(&self, stream: AcceptStream, prev: Box<dyn Any + Send>, rc: Weak<()>) {
if let Ok(prev) = prev.downcast() {
VHostTarget::handle_stream(self, stream, *prev);
VHostTarget::handle_stream(self, stream, *prev, rc);
}
}
fn eq(&self, other: &dyn DynVHostTargetT<A>) -> bool {
@@ -250,21 +252,27 @@ impl<A: Accept + 'static> PartialEq for DynVHostTarget<A> {
}
}
impl<A: Accept + 'static> Eq for DynVHostTarget<A> {}
struct Preprocessed<A: Accept>(DynVHostTarget<A>, Box<dyn Any + Send>);
struct Preprocessed<A: Accept>(DynVHostTarget<A>, Weak<()>, Box<dyn Any + Send>);
impl<A: Accept> fmt::Debug for Preprocessed<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(self.0).0.fmt(f)
}
}
impl<A: Accept + 'static> DynVHostTarget<A> {
async fn into_preprocessed(
self,
rc: Weak<()>,
prev: ServerConfig,
hello: &ClientHello<'_>,
metadata: &<A as Accept>::Metadata,
) -> Option<(ServerConfig, Preprocessed<A>)> {
let (cfg, res) = self.0.preprocess(prev, hello, metadata).await?;
Some((cfg, Preprocessed(self, res)))
Some((cfg, Preprocessed(self, rc, res)))
}
}
impl<A: Accept + 'static> Preprocessed<A> {
fn finish(self, stream: AcceptStream) {
(self.0).0.handle_stream(stream, self.1);
(self.0).0.handle_stream(stream, self.2, self.1);
}
}
@@ -278,6 +286,7 @@ pub struct ProxyTarget {
impl PartialEq for ProxyTarget {
fn eq(&self, other: &Self) -> bool {
self.filter == other.filter
&& self.acme == other.acme
&& self.addr == other.addr
&& self.connect_ssl.as_ref().map(Arc::as_ptr)
== other.connect_ssl.as_ref().map(Arc::as_ptr)
@@ -293,6 +302,9 @@ where
type PreprocessRes = AcceptStream;
fn filter(&self, metadata: &<A as Accept>::Metadata) -> bool {
let info = extract::<GatewayInfo, _>(metadata);
if info.is_none() {
tracing::warn!("No GatewayInfo on metadata");
}
info.as_ref()
.map_or(true, |i| self.filter.filter(&i.id, &i.info))
}
@@ -303,7 +315,7 @@ where
&'a self,
mut prev: ServerConfig,
hello: &'a ClientHello<'a>,
metadata: &'a <A as Accept>::Metadata,
_: &'a <A as Accept>::Metadata,
) -> Option<(ServerConfig, Self::PreprocessRes)> {
let tcp_stream = TcpStream::connect(self.addr)
.await
@@ -344,13 +356,16 @@ where
}
Some((prev, Box::pin(tcp_stream)))
}
fn handle_stream(&self, mut stream: AcceptStream, mut prev: Self::PreprocessRes) {
tokio::spawn(async move { tokio::io::copy_bidirectional(&mut stream, &mut prev).await });
fn handle_stream(&self, mut stream: AcceptStream, mut prev: Self::PreprocessRes, rc: Weak<()>) {
tokio::spawn(async move {
WeakFuture::new(rc, tokio::io::copy_bidirectional(&mut stream, &mut prev)).await
});
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum AlpnInfo {
Reflect,
Specified(Vec<MaybeUtf8String>),
@@ -434,16 +449,16 @@ where
return Some(prev);
}
let target = self.0.peek(|m| {
let (target, rc) = self.0.peek(|m| {
m.get(&hello.server_name().map(InternedString::from))
.into_iter()
.flatten()
.filter(|(_, rc)| rc.strong_count() > 0)
.find(|(t, _)| t.0.filter(metadata))
.map(|(e, _)| e.clone())
.map(|(t, rc)| (t.clone(), rc.clone()))
})?;
let (prev, store) = target.into_preprocessed(prev, hello, metadata).await?;
let (prev, store) = target.into_preprocessed(rc, prev, hello, metadata).await?;
self.1 = Some(store);
@@ -478,6 +493,14 @@ struct VHostListenerMetadata<A: Accept> {
inner: TlsMetadata<A::Metadata>,
preprocessed: Preprocessed<A>,
}
impl<A: Accept> fmt::Debug for VHostListenerMetadata<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VHostListenerMetadata")
.field("inner", &self.inner)
.field("preprocessed", &self.preprocessed)
.finish()
}
}
impl<M, A> Accept for VHostListener<M, A>
where
for<'a> M: HasModel<Model = Model<M>>
@@ -635,6 +658,7 @@ impl<A: Accept> VHostServer<A> {
changed = true;
Arc::new(())
};
targets.retain(|_, rc| rc.strong_count() > 0);
targets.insert(target, Arc::downgrade(&rc));
writable.insert(hostname, targets);
res = Ok(rc);

View File

@@ -1,3 +1,4 @@
use core::fmt;
use std::any::Any;
use std::collections::BTreeMap;
use std::future::Future;
@@ -68,7 +69,7 @@ pub fn extract<
metadata: &M,
) -> Option<T> {
let mut visitor = ExtractVisitor(None);
visitor.visit(metadata);
metadata.visit(&mut visitor);
visitor.0
}
@@ -84,7 +85,7 @@ impl<V: MetadataVisitor> Visit<V> for TcpMetadata {
}
pub trait Accept {
type Metadata;
type Metadata: fmt::Debug;
fn poll_accept(
&mut self,
cx: &mut std::task::Context<'_>,
@@ -144,7 +145,7 @@ where
}
}
#[derive(Clone, VisitFields)]
#[derive(Debug, Clone, VisitFields)]
pub struct MapListenerMetadata<K, M> {
pub inner: M,
pub key: K,
@@ -162,7 +163,7 @@ where
impl<K, A> Accept for BTreeMap<K, A>
where
K: Clone,
K: Clone + fmt::Debug,
A: Accept,
{
type Metadata = MapListenerMetadata<K, A::Metadata>;
@@ -218,40 +219,38 @@ trait DynAcceptT: Send + Sync {
fn poll_accept(
&mut self,
cx: &mut std::task::Context<'_>,
) -> Poll<
Result<
(
Box<dyn for<'a> Visit<ExtensionVisitor<'a>> + Send + Sync>,
AcceptStream,
),
Error,
>,
>;
) -> Poll<Result<(DynMetadata, AcceptStream), Error>>;
}
impl<A> DynAcceptT for A
where
A: Accept + Send + Sync,
for<'a> <A as Accept>::Metadata: Visit<ExtensionVisitor<'a>> + Send + Sync + 'static,
<A as Accept>::Metadata: DynMetadataT + 'static,
{
fn poll_accept(
&mut self,
cx: &mut std::task::Context<'_>,
) -> Poll<
Result<
(
Box<dyn for<'a> Visit<ExtensionVisitor<'a>> + Send + Sync>,
AcceptStream,
),
Error,
>,
> {
) -> Poll<Result<(DynMetadata, AcceptStream), Error>> {
let (metadata, stream) = ready!(Accept::poll_accept(self, cx)?);
Poll::Ready(Ok((Box::new(metadata), stream)))
Poll::Ready(Ok((DynMetadata(Box::new(metadata)), stream)))
}
}
pub struct DynAccept(Box<dyn DynAcceptT>);
trait DynMetadataT: for<'a> Visit<ExtensionVisitor<'a>> + fmt::Debug + Send + Sync {}
impl<T> DynMetadataT for T where for<'a> T: Visit<ExtensionVisitor<'a>> + fmt::Debug + Send + Sync {}
#[derive(Debug)]
pub struct DynMetadata(Box<dyn DynMetadataT>);
impl<'a> Visit<ExtensionVisitor<'a>> for DynMetadata {
fn visit(
&self,
visitor: &mut ExtensionVisitor<'a>,
) -> <ExtensionVisitor<'a> as Visitor>::Result {
self.0.visit(visitor)
}
}
impl Accept for DynAccept {
type Metadata = Box<dyn for<'a> Visit<ExtensionVisitor<'a>> + Send + Sync>;
type Metadata = DynMetadata;
fn poll_accept(
&mut self,
cx: &mut std::task::Context<'_>,
@@ -325,7 +324,7 @@ impl Acceptor<Vec<DynAccept>> {
}
impl<K> Acceptor<BTreeMap<K, TcpListener>>
where
K: Ord + Clone + Send + Sync + 'static,
K: Ord + Clone + fmt::Debug + Send + Sync + 'static,
{
pub async fn bind_map(
listen: impl IntoIterator<Item = (K, SocketAddr)>,
@@ -347,7 +346,7 @@ where
}
impl<K> Acceptor<BTreeMap<K, DynAccept>>
where
K: Ord + Clone + Send + Sync + 'static,
K: Ord + Clone + fmt::Debug + Send + Sync + 'static,
{
pub async fn bind_map_dyn(
listen: impl IntoIterator<Item = (K, SocketAddr)>,

View File

@@ -343,23 +343,22 @@ pub async fn remove(ctx: RpcContext, SsidParams { ssid }: SsidParams) -> Result<
.result?;
Ok(())
}
#[derive(serde::Serialize, serde::Deserialize, TS)]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WifiListInfo {
ssids: HashMap<Ssid, SignalStrength>,
connected: Option<Ssid>,
#[ts(type = "sttring | null")]
country: Option<CountryCode>,
ethernet: bool,
available_wifi: Vec<WifiListOut>,
}
#[derive(serde::Serialize, serde::Deserialize, Clone, TS)]
#[derive(serde::Serialize, serde::Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WifiListInfoLow {
strength: SignalStrength,
security: Vec<String>,
}
#[derive(serde::Serialize, serde::Deserialize, TS)]
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WifiListOut {
ssid: Ssid,
@@ -590,7 +589,7 @@ pub struct NetworkId(String);
/// Ssid are the names of the wifis, usually human readable.
#[derive(
Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, TS,
Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct Ssid(String);
@@ -607,7 +606,6 @@ pub struct Ssid(String);
Hash,
serde::Serialize,
serde::Deserialize,
TS,
)]
pub struct SignalStrength(u8);

View File

@@ -388,7 +388,7 @@ impl Map for Notifications {
}
}
#[derive(Debug, Serialize, Deserialize, HasModel, TS)]
#[derive(Debug, Serialize, Deserialize, HasModel)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
pub struct Notification {
@@ -403,7 +403,7 @@ pub struct Notification {
pub seen: bool,
}
#[derive(Debug, Serialize, Deserialize, TS)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NotificationWithId {
id: u32,

View File

@@ -356,7 +356,10 @@ pub async fn execute<C: Context>(
let mut install = Command::new("chroot");
install.arg(overlay.path()).arg("grub-install");
if tokio::fs::metadata("/sys/firmware/efi").await.is_err() {
install.arg("--target=i386-pc");
match ARCH {
"x86_64" => install.arg("--target=i386-pc"),
_ => &mut install,
};
} else {
match ARCH {
"x86_64" => install.arg("--target=x86_64-efi"),
@@ -372,7 +375,7 @@ pub async fn execute<C: Context>(
Command::new("chroot")
.arg(overlay.path())
.arg("update-grub2")
.arg("update-grub")
.invoke(crate::ErrorKind::Grub)
.await?;
dev.unmount(false).await?;

View File

@@ -196,6 +196,7 @@ impl std::ops::AddAssign<u64> for Progress {
}
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct NamedProgress {
#[ts(type = "string")]
pub name: InternedString,
@@ -203,6 +204,7 @@ pub struct NamedProgress {
}
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct FullProgress {
pub overall: Progress,
pub phases: Vec<NamedProgress>,

View File

@@ -32,7 +32,6 @@ pub fn admin_api<C: Context>() -> ParentHandler<C> {
"add",
from_fn_async(cli_add_admin)
.no_display()
.no_ts()
.with_about("Add admin signer"),
)
.subcommand(
@@ -73,7 +72,7 @@ fn signers_api<C: Context>() -> ParentHandler<C> {
)
.subcommand(
"add",
from_fn_async(cli_add_signer).no_ts().with_about("Add signer"),
from_fn_async(cli_add_signer).with_about("Add signer"),
)
.subcommand(
"edit",
@@ -173,6 +172,7 @@ pub async fn add_signer(ctx: RegistryContext, signer: SignerInfo) -> Result<Guid
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct EditSignerParams {
pub id: Guid,
#[arg(short = 'n', long)]
@@ -280,6 +280,7 @@ pub async fn cli_add_signer(
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddAdminParams {
pub signer: Guid,
}
@@ -304,6 +305,7 @@ pub async fn add_admin(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveAdminParams {
pub signer: Guid,
}

View File

@@ -22,6 +22,7 @@ use crate::upload::UploadingFile;
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryAsset<Commitment> {
#[ts(type = "string")]
pub published_at: DateTime<Utc>,

View File

@@ -22,24 +22,18 @@ pub fn db_api<C: Context>() -> ParentHandler<C> {
"dump",
from_fn_async(cli_dump)
.with_display_serializable()
.no_ts()
.with_about("Filter/query db to display tables and records"),
)
.subcommand(
"dump",
from_fn_async(dump)
.with_metadata("admin", Value::Bool(true))
.no_cli()
.custom_ts(
DumpParams::inline_flattened(),
format!("{{ id: number; value: unknown }}"),
),
.no_cli(),
)
.subcommand(
"apply",
from_fn_async(cli_apply)
.no_display()
.no_ts()
.with_about("Update a db record"),
)
.subcommand(

View File

@@ -47,6 +47,7 @@ pub fn info_api<C: Context>() -> ParentHandler<C, WithIoFormat<Empty>> {
#[derive(Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RegistryInfo {
pub name: Option<String>,
pub icon: Option<DataUrl<'static>>,
@@ -65,6 +66,7 @@ pub async fn get_info(ctx: RegistryContext) -> Result<RegistryInfo, Error> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetNameParams {
pub name: String,
}
@@ -81,6 +83,7 @@ pub async fn set_name(
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetIconParams {
pub icon: DataUrl<'static>,
}
@@ -98,6 +101,7 @@ pub async fn set_icon(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CliSetIconParams {
pub icon: PathBuf,
}

View File

@@ -11,6 +11,7 @@ use crate::context::CliContext;
use crate::middleware::cors::Cors;
use crate::middleware::signature::SignatureAuth;
use crate::net::static_server::{bad_request, not_found, server_error};
use crate::net::web_server::{Accept, WebServer};
use crate::prelude::*;
use crate::registry::context::RegistryContext;
use crate::registry::device_info::DeviceInfoMiddleware;
@@ -42,6 +43,7 @@ impl RegistryDatabase {}
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct FullIndex {
pub name: Option<String>,
pub icon: Option<DataUrl<'static>>,

View File

@@ -75,6 +75,7 @@ pub fn remove_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddAssetParams {
#[ts(type = "string")]
pub version: Version,
@@ -282,6 +283,7 @@ pub async fn cli_add_asset(
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveAssetParams {
#[ts(type = "string")]
pub version: Version,

View File

@@ -30,7 +30,6 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
"iso",
from_fn_async(cli_get_os_asset)
.no_display()
.no_ts()
.with_about("Download iso"),
)
.subcommand("img", from_fn_async(get_img).no_cli())
@@ -38,7 +37,6 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
"img",
from_fn_async(cli_get_os_asset)
.no_display()
.no_ts()
.with_about("Download img"),
)
.subcommand("squashfs", from_fn_async(get_squashfs).no_cli())
@@ -46,13 +44,13 @@ pub fn get_api<C: Context>() -> ParentHandler<C> {
"squashfs",
from_fn_async(cli_get_os_asset)
.no_display()
.no_ts()
.with_about("Download squashfs"),
)
}
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetOsAssetParams {
#[ts(type = "string")]
pub version: Version,

View File

@@ -11,7 +11,6 @@ pub fn asset_api<C: Context>() -> ParentHandler<C> {
"add",
from_fn_async(add::cli_add_asset)
.no_display()
.no_ts()
.with_about("Add asset to registry"),
)
.subcommand("remove", add::remove_api::<C>())
@@ -20,7 +19,6 @@ pub fn asset_api<C: Context>() -> ParentHandler<C> {
"sign",
from_fn_async(sign::cli_sign_asset)
.no_display()
.no_ts()
.with_about("Sign file and add to registry index"),
)
// TODO: remove signature api

View File

@@ -49,6 +49,7 @@ pub fn sign_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SignAssetParams {
#[ts(type = "string")]
version: Version,

View File

@@ -14,6 +14,7 @@ use crate::sign::commitment::blake3::Blake3Commitment;
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct OsIndex {
pub versions: OsVersionInfoMap,
}
@@ -36,6 +37,7 @@ impl Map for OsVersionInfoMap {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct OsVersionInfo {
pub headline: String,
pub release_notes: String,

View File

@@ -46,10 +46,6 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
"get",
from_fn_async(get_version)
.with_metadata("get_device_info", Value::Bool(true))
.custom_ts(
GetOsVersionParams::inline_flattened(),
BTreeMap::<String, OsVersionInfo>::inline_flattened(),
)
.with_display_serializable()
.with_custom_display_fn(|handle, result| {
display_version_info(handle.params, result)
@@ -62,6 +58,7 @@ pub fn version_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddVersionParams {
#[ts(type = "string")]
pub version: Version,
@@ -109,6 +106,7 @@ pub async fn add_version(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveVersionParams {
#[ts(type = "string")]
pub version: Version,
@@ -133,6 +131,7 @@ pub async fn remove_version(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetOsVersionParams {
#[ts(type = "string | null")]
#[arg(long = "src")]

View File

@@ -45,6 +45,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct VersionSignerParams {
#[ts(type = "string")]
pub version: Version,
@@ -107,6 +108,7 @@ pub async fn remove_version_signer(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ListVersionSignersParams {
#[ts(type = "string")]
pub version: Version,

View File

@@ -26,6 +26,7 @@ use crate::util::io::TrackingIO;
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddPackageParams {
#[ts(type = "string")]
pub url: Url,
@@ -162,6 +163,7 @@ pub async fn cli_add_package(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemovePackageParams {
pub id: PackageId,
pub version: VersionString,

View File

@@ -61,6 +61,7 @@ pub fn category_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddCategoryParams {
#[ts(type = "string")]
pub id: InternedString,
@@ -86,6 +87,7 @@ pub async fn add_category(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemoveCategoryParams {
#[ts(type = "string")]
pub id: InternedString,
@@ -110,6 +112,7 @@ pub async fn remove_category(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct AddPackageToCategoryParams {
#[ts(type = "string")]
pub id: InternedString,
@@ -138,6 +141,7 @@ pub async fn add_package(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RemovePackageFromCategoryParams {
#[ts(type = "string")]
pub id: InternedString,

View File

@@ -19,6 +19,7 @@ use crate::util::serde::{WithIoFormat, display_serializable};
Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS, ValueEnum,
)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum PackageDetailLevel {
None,
Short,
@@ -32,6 +33,7 @@ impl Default for PackageDetailLevel {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct PackageInfoShort {
pub release_notes: String,
}
@@ -39,6 +41,7 @@ pub struct PackageInfoShort {
#[derive(Debug, Deserialize, Serialize, TS, Parser)]
#[serde(rename_all = "camelCase")]
#[command(rename_all = "kebab-case")]
#[ts(export)]
pub struct GetPackageParams {
pub id: Option<PackageId>,
#[ts(type = "string | null")]
@@ -57,6 +60,7 @@ pub struct GetPackageParams {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetPackageResponse {
#[ts(type = "string[]")]
pub categories: BTreeSet<InternedString>,
@@ -99,6 +103,7 @@ impl GetPackageResponse {
#[derive(Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetPackageResponseFull {
#[ts(type = "string[]")]
pub categories: BTreeSet<InternedString>,

View File

@@ -23,6 +23,7 @@ use crate::sign::{AnySignature, AnyVerifyingKey};
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct PackageIndex {
pub categories: BTreeMap<InternedString, Category>,
pub packages: BTreeMap<PackageId, PackageInfo>,
@@ -31,6 +32,7 @@ pub struct PackageIndex {
#[derive(Debug, Default, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct PackageInfo {
pub authorized: BTreeSet<Guid>,
pub versions: BTreeMap<VersionString, PackageVersionInfo>,
@@ -41,6 +43,7 @@ pub struct PackageInfo {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct Category {
pub name: String,
}
@@ -48,6 +51,7 @@ pub struct Category {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct DependencyMetadata {
#[ts(type = "string | null")]
pub title: Option<InternedString>,
@@ -59,6 +63,7 @@ pub struct DependencyMetadata {
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct PackageVersionInfo {
#[ts(type = "string")]
pub title: InternedString,

View File

@@ -29,7 +29,6 @@ pub fn package_api<C: Context>() -> ParentHandler<C> {
"add",
from_fn_async(add::cli_add_package)
.no_display()
.no_ts()
.with_about("Add package to registry index"),
)
.subcommand(

View File

@@ -45,6 +45,7 @@ pub fn signer_api<C: Context>() -> ParentHandler<C> {
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct PackageSignerParams {
pub id: PackageId,
pub signer: Guid,
@@ -106,6 +107,7 @@ pub async fn remove_package_signer(
#[derive(Debug, Deserialize, Serialize, Parser, TS)]
#[command(rename_all = "kebab-case")]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ListPackageSignersParams {
pub id: PackageId,
}

View File

@@ -15,6 +15,7 @@ use crate::sign::{AnySignature, AnyVerifyingKey, SignatureScheme};
#[derive(Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct SignerInfo {
pub name: String,
pub contact: Vec<ContactInfo>,
@@ -23,6 +24,7 @@ pub struct SignerInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
// TODO: better types
pub enum ContactInfo {
Email(String),
@@ -59,6 +61,7 @@ impl ValueParserFactory for ContactInfo {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum AcceptSigners {
#[serde(skip)]
Accepted,

View File

@@ -25,13 +25,11 @@ pub fn s9pk() -> ParentHandler<CliContext> {
"pack",
from_fn_async(super::v2::pack::pack)
.no_display()
.no_ts()
.with_about("Package s9pk input files into valid s9pk"),
)
.subcommand(
"list-ingredients",
from_fn_async(super::v2::pack::list_ingredients)
.no_ts()
.with_custom_display_fn(|_, ingredients| {
ingredients
.into_iter()
@@ -51,17 +49,16 @@ pub fn s9pk() -> ParentHandler<CliContext> {
)
.subcommand(
"edit",
edit().no_ts().with_about("Commands to add an image to an s9pk or edit the manifest"),
edit().with_about("Commands to add an image to an s9pk or edit the manifest"),
)
.subcommand(
"inspect",
inspect().no_ts().with_about("Commands to display file paths, file contents, or manifest"),
inspect().with_about("Commands to display file paths, file contents, or manifest"),
)
.subcommand(
"convert",
from_fn_async(convert)
.no_display()
.no_ts()
.with_about("Convert s9pk from v1 to v2"),
)
}

View File

@@ -5,7 +5,7 @@ use color_eyre::eyre::eyre;
use exver::{Version, VersionRange};
use imbl_value::InternedString;
pub use models::PackageId;
use models::{mime, ImageId, VolumeId};
use models::{ImageId, VolumeId, mime};
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use url::Url;
@@ -16,15 +16,10 @@ use crate::s9pk::git_hash::GitHash;
use crate::s9pk::merkle_archive::directory_contents::DirectoryContents;
use crate::s9pk::merkle_archive::expected::{Expected, Filter};
use crate::s9pk::v2::pack::ImageConfig;
use crate::util::serde::Regex;
use crate::util::VersionString;
use crate::util::serde::Regex;
use crate::version::{Current, VersionT};
#[test]
fn export_bindings_manifest() {
Manifest::export_all_to("./bindings/manifest").unwrap();
}
fn current_version() -> Version {
Current::default().semver()
}
@@ -32,6 +27,7 @@ fn current_version() -> Version {
#[derive(Clone, Debug, Deserialize, Serialize, HasModel, TS)]
#[serde(rename_all = "camelCase")]
#[model = "Model<Self>"]
#[ts(export)]
pub struct Manifest {
pub id: PackageId,
#[ts(type = "string")]
@@ -171,6 +167,7 @@ impl Manifest {
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct HardwareRequirements {
#[serde(default)]
pub device: Vec<DeviceFilter>,
@@ -182,6 +179,7 @@ pub struct HardwareRequirements {
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct DeviceFilter {
#[ts(type = "\"processor\" | \"display\"")]
pub class: InternedString,
@@ -191,6 +189,7 @@ pub struct DeviceFilter {
}
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct Description {
pub short: String,
pub long: String,
@@ -215,6 +214,7 @@ impl Description {
#[derive(Clone, Debug, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct Alerts {
pub install: Option<String>,
pub uninstall: Option<String>,

View File

@@ -248,6 +248,7 @@ impl PackParams {
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ImageConfig {
pub source: ImageSource,
#[ts(type = "string[]")]
@@ -335,6 +336,7 @@ impl clap::FromArgMatches for ImageConfig {
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
#[ts(export)]
pub enum BuildArg {
String(String),
EnvVar { env: String },
@@ -342,6 +344,7 @@ pub enum BuildArg {
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum ImageSource {
Packed,
#[serde(rename_all = "camelCase")]
@@ -623,6 +626,7 @@ fn tar2sqfs(dest: impl AsRef<Path>) -> Result<Command, Error> {
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct ImageMetadata {
pub workdir: PathBuf,
#[ts(type = "string")]

View File

@@ -1,9 +1,9 @@
use std::collections::BTreeSet;
use models::{ActionId, PackageId, ReplayId};
use rpc_toolkit::{from_fn_async, Context, HandlerExt, ParentHandler};
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn_async};
use crate::action::{display_action_result, ActionInput, ActionResult};
use crate::action::{ActionInput, ActionResult, display_action_result};
use crate::db::model::package::{
ActionMetadata, Task, TaskCondition, TaskEntry, TaskSeverity, TaskTrigger,
};
@@ -44,6 +44,7 @@ pub fn action_api<C: Context>() -> ParentHandler<C> {
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExportActionParams {
id: ActionId,
@@ -76,6 +77,7 @@ pub async fn export_action(
}
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ClearActionsParams {
#[arg(long)]
@@ -108,6 +110,7 @@ async fn clear_actions(
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetActionInputParams {
#[serde(default)]
#[ts(skip)]
@@ -145,6 +148,7 @@ async fn get_action_input(
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct RunActionParams {
#[serde(default)]
#[ts(skip)]
@@ -153,8 +157,8 @@ pub struct RunActionParams {
#[ts(optional)]
package_id: Option<PackageId>,
action_id: ActionId,
#[ts(optional, type = "unknown")]
input: Option<Value>,
#[ts(type = "any")]
input: Value,
}
async fn run_action(
context: EffectContext,
@@ -167,8 +171,6 @@ async fn run_action(
) -> Result<Option<ActionResult>, Error> {
let context = context.deref()?;
let input = input.unwrap_or_default();
let package_id = package_id.as_ref().unwrap_or(&context.seed.id);
if package_id != &context.seed.id {
@@ -193,6 +195,7 @@ async fn run_action(
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CreateTaskParams {
#[serde(default)]
#[ts(skip)]
@@ -280,6 +283,7 @@ async fn create_task(
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(type = "{ only: string[] } | { except: string[] }")]
#[ts(export)]
pub struct ClearTasksParams {
#[arg(long, conflicts_with = "except")]
pub only: Option<Vec<ReplayId>>,

View File

@@ -293,6 +293,7 @@ impl CallbackHandlers {
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(type = "{ only: number[] } | { except: number[] }")]
#[ts(export)]
pub struct ClearCallbacksParams {
#[arg(long, conflicts_with = "except")]
pub only: Option<Vec<CallbackId>>,

View File

@@ -35,6 +35,7 @@ pub async fn shutdown(context: EffectContext, EventId { event_id }: EventId) ->
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetStatusParams {
#[ts(optional)]
pub package_id: Option<PackageId>,
@@ -75,6 +76,7 @@ pub async fn get_status(
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum SetMainStatusStatus {
Running,
Stopped,
@@ -98,6 +100,7 @@ impl ValueParserFactory for SetMainStatusStatus {
#[derive(Debug, Clone, Serialize, Deserialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetMainStatus {
status: SetMainStatusStatus,
}

View File

@@ -22,6 +22,7 @@ use crate::status::health_check::NamedHealthCheckResult;
use crate::volume::data_dir;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct MountTarget {
package_id: PackageId,
@@ -31,6 +32,7 @@ pub struct MountTarget {
filetype: FileType,
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct MountParams {
location: PathBuf,
@@ -96,6 +98,7 @@ pub async fn get_installed_packages(context: EffectContext) -> Result<BTreeSet<P
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum DependencyKind {
Exists,
Running,
@@ -103,6 +106,7 @@ pub enum DependencyKind {
#[derive(Debug, Clone, Deserialize, Serialize, TS)]
#[serde(rename_all = "camelCase", tag = "kind")]
#[serde(rename_all_fields = "camelCase")]
#[ts(export)]
pub enum DependencyRequirement {
Running {
id: PackageId,
@@ -166,6 +170,7 @@ impl ValueParserFactory for DependencyRequirement {
#[derive(Deserialize, Serialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[command(rename_all = "camelCase")]
#[ts(export)]
pub struct SetDependenciesParams {
dependencies: Vec<DependencyRequirement>,
}
@@ -266,12 +271,14 @@ pub async fn get_dependencies(context: EffectContext) -> Result<Vec<DependencyRe
#[derive(Debug, Clone, Serialize, Deserialize, Parser, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CheckDependenciesParam {
#[ts(optional)]
package_ids: Option<Vec<PackageId>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct CheckDependenciesResult {
package_id: PackageId,
#[ts(type = "string | null")]

View File

@@ -6,6 +6,7 @@ use crate::status::health_check::NamedHealthCheckResult;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct SetHealth {
id: HealthCheckId,
#[serde(flatten)]

View File

@@ -1,18 +1,17 @@
use std::net::Ipv4Addr;
use rpc_toolkit::{from_fn, from_fn_async, from_fn_blocking, Context, HandlerExt, ParentHandler};
use ts_rs::TS;
use rpc_toolkit::{Context, HandlerExt, ParentHandler, from_fn, from_fn_async, from_fn_blocking};
use crate::prelude::*;
use crate::service::cli::ContainerCliContext;
use crate::service::effects::context::EffectContext;
use crate::{echo, HOST_IP};
use crate::{HOST_IP, echo};
mod action;
pub mod callbacks;
pub mod context;
mod control;
pub mod dependency;
mod dependency;
mod health;
mod net;
mod prelude;
@@ -20,22 +19,6 @@ mod subcontainer;
mod system;
mod version;
#[test]
fn export_bindings_service_effects_api() {
use rpc_toolkit::HandlerTS;
std::fs::create_dir_all("./bindings").unwrap();
std::fs::write(
"./bindings/service-effects-api.ts",
format!(
"export type ServiceEffectsApi = {}",
handler::<EffectContext>().type_info().unwrap()
)
.as_bytes(),
)
.unwrap();
}
pub fn handler<C: Context>() -> ParentHandler<C> {
ParentHandler::new()
.subcommand("git-info", from_fn(|_: C| crate::version::git_info()))
@@ -113,31 +96,20 @@ pub fn handler<C: Context>() -> ParentHandler<C> {
ParentHandler::<C>::new()
.subcommand(
"launch",
from_fn_blocking(subcontainer::launch).no_display().no_ts(),
from_fn_blocking(subcontainer::launch).no_display(),
)
.subcommand(
"launch-init",
from_fn_blocking(subcontainer::launch_init)
.no_display()
.no_ts(),
)
.subcommand(
"exec",
from_fn_blocking(subcontainer::exec).no_display().no_ts(),
from_fn_blocking(subcontainer::launch_init).no_display(),
)
.subcommand("exec", from_fn_blocking(subcontainer::exec).no_display())
.subcommand(
"exec-command",
from_fn_blocking(subcontainer::exec_command)
.no_display()
.no_ts(),
from_fn_blocking(subcontainer::exec_command).no_display(),
)
.subcommand(
"create-fs",
from_fn_async(subcontainer::create_subcontainer_fs)
.custom_ts(
subcontainer::CreateSubcontainerFsParams::inline_flattened(),
"[string, string]".into(),
)
.with_custom_display_fn(|_, (path, _)| Ok(println!("{}", path.display())))
.with_call_remote::<ContainerCliContext>(),
)

View File

@@ -5,6 +5,7 @@ use crate::service::effects::prelude::*;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct BindParams {
id: HostId,
internal_port: u16,
@@ -29,6 +30,7 @@ pub async fn bind(
}
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ClearBindingsParams {
#[serde(default)]
@@ -50,6 +52,7 @@ pub async fn clear_bindings(
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct GetServicePortForwardParams {
#[ts(optional)]

View File

@@ -7,6 +7,7 @@ use crate::service::rpc::CallbackId;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetHostInfoParams {
host_id: HostId,
#[ts(optional)]

View File

@@ -8,6 +8,7 @@ use crate::service::rpc::CallbackId;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetContainerIpParams {
#[ts(optional)]
package_id: Option<PackageId>,

View File

@@ -9,6 +9,7 @@ use crate::service::effects::prelude::*;
use crate::service::rpc::CallbackId;
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ExportServiceInterfaceParams {
id: ServiceInterfaceId,
@@ -82,6 +83,7 @@ pub async fn export_service_interface(
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetServiceInterfaceParams {
#[ts(optional)]
package_id: Option<PackageId>,
@@ -122,6 +124,7 @@ pub async fn get_service_interface(
}
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ListServiceInterfacesParams {
#[ts(optional)]
@@ -164,6 +167,7 @@ pub async fn list_service_interfaces(
}
#[derive(Debug, Clone, Serialize, Deserialize, TS, Parser)]
#[ts(export)]
#[serde(rename_all = "camelCase")]
pub struct ClearServiceInterfacesParams {
pub except: Vec<ServiceInterfaceId>,

View File

@@ -14,6 +14,7 @@ use crate::util::serde::Pem;
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, TS, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub enum Algorithm {
Ecdsa,
Ed25519,
@@ -21,6 +22,7 @@ pub enum Algorithm {
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetSslCertificateParams {
#[ts(type = "string[]")]
hostnames: BTreeSet<InternedString>,
@@ -142,6 +144,7 @@ pub async fn get_ssl_certificate(
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export)]
pub struct GetSslKeyParams {
#[ts(type = "string[]")]
hostnames: BTreeSet<InternedString>,

Some files were not shown because too many files have changed in this diff Show More