Skip to content
Merged

Dev #24

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b07029d
fix ci module ordering rigor
blackdragoon26 Jul 7, 2026
0567f41
Merge pull request #17 from blackdragoon26/agent/ci-module-stable-order
blackdragoon26 Jul 7, 2026
66c042a
harden upload lifecycle controls
blackdragoon26 Jul 7, 2026
2ed1646
address upload lifecycle review
blackdragoon26 Jul 7, 2026
3223172
address store task review
blackdragoon26 Jul 7, 2026
b1d07ed
Merge pull request #18 from blackdragoon26/agent/upload-cleanup-rate-…
blackdragoon26 Jul 7, 2026
02be692
add csrf mutation guard
blackdragoon26 Jul 7, 2026
4cd5333
Merge pull request #19 from blackdragoon26/agent/csrf-protection
blackdragoon26 Jul 7, 2026
3186032
align runtime operational limits
blackdragoon26 Jul 7, 2026
5add82e
address operational review
blackdragoon26 Jul 7, 2026
bc82dd6
Merge pull request #20 from blackdragoon26/agent/operational-polish
blackdragoon26 Jul 7, 2026
e489240
add visible author credit
blackdragoon26 Jul 7, 2026
38bb694
Merge pull request #21 from blackdragoon26/agent/ui-author-credit
blackdragoon26 Jul 7, 2026
f22e7cf
document terminal release downloads
blackdragoon26 Jul 7, 2026
16c7442
point installer docs at dev branch
blackdragoon26 Jul 7, 2026
a6f2584
address terminal download review
blackdragoon26 Jul 7, 2026
38c7e31
Merge pull request #22 from blackdragoon26/agent/terminal-downloads
blackdragoon26 Jul 7, 2026
dc75542
add product website surface
blackdragoon26 Jul 7, 2026
86c249c
point website install snippet at dev
blackdragoon26 Jul 7, 2026
2a5b66b
refine product website surface
blackdragoon26 Jul 7, 2026
256ab5f
Merge pull request #23 from blackdragoon26/agent/product-website
blackdragoon26 Jul 7, 2026
97ab694
polish website install surface
blackdragoon26 Jul 7, 2026
7fb5a60
pin vercel deployments to main
blackdragoon26 Jul 7, 2026
87e1181
address final pr review feedback
blackdragoon26 Jul 7, 2026
bd4a1dd
fix installer for legacy release checksums
blackdragoon26 Jul 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [ "main", "dev" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "dev" ]

jobs:
build-and-test:
Expand All @@ -21,4 +21,4 @@ jobs:
run: go build -v ./...

- name: Test
run: go test -v ./...
run: go test -race -v ./...
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
data/
awesomeProject
.gocache
.vercel
5 changes: 4 additions & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ archives:
format: zip
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}"

checksum:
name_template: "checksums.txt"

changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^test:"
5 changes: 5 additions & 0 deletions .vercelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.git
.gocache
.idea
data
awesomeProject
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,33 @@ http://192.168.1.22:8080

Open that address from another device connected to the same Wi-Fi.

## Terminal Download

Install the latest release with either `curl` or `wget`:

```bash
curl -fsSL https://raw.githubusercontent.com/blackdragoon26/Do-It/main/scripts/install.sh | sh
```

```bash
wget -qO- https://raw.githubusercontent.com/blackdragoon26/Do-It/main/scripts/install.sh | sh
```

The installer downloads the matching GitHub release archive for Linux or macOS on `amd64`/`arm64`, then installs `doit` into `~/.local/bin`. If you cloned the repository or downloaded `scripts/install.sh` locally, override the destination or version when needed:

```bash
DOIT_INSTALL_DIR=/usr/local/bin DOIT_VERSION=v1.0.0 sh scripts/install.sh
```

Manual download format:

```text
https://github.com/blackdragoon26/Do-It/releases/latest/download/Do-It_linux_amd64.tar.gz
https://github.com/blackdragoon26/Do-It/releases/latest/download/Do-It_linux_arm64.tar.gz
https://github.com/blackdragoon26/Do-It/releases/latest/download/Do-It_darwin_amd64.tar.gz
https://github.com/blackdragoon26/Do-It/releases/latest/download/Do-It_darwin_arm64.tar.gz
```

## Data Storage

By default, Do-It writes local app data under:
Expand Down
6 changes: 4 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ For the current product, HTTP plus SSE is simpler and easier to debug while lear
- Uploads are local to one server device.
- Device presence is approximate because it uses IP plus user agent.
- No offline edit queue yet.
- Each mutation currently broadcasts a full task snapshot to every connected browser. That is simple and reliable for a LAN-scale app, but large datasets should move toward diff-based updates or paged sync.

## Next Architecture Upgrades

Expand All @@ -252,5 +253,6 @@ Best order:
2. Pairing code or local auth.
3. Better backup/export.
4. Drag-to-reparent graph nodes.
5. Optional gRPC/Connect-Go API.
6. mDNS discovery, so devices can open `doit.local`.
5. Diff-based live sync for large task graphs.
6. Optional gRPC/Connect-Go API.
7. mDNS discovery, so devices can open `doit.local`.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module awesomeProject
module github.com/blackdragoon26/Do-It

go 1.26
29 changes: 27 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package main

import (
"context"
"embed"
"io/fs"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
)

Expand Down Expand Up @@ -42,8 +45,30 @@ func main() {
log.Printf("LAN device URL: %s", url)
}

if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("serve: %v", err)
serverErr := make(chan error, 1)
go func() {
serverErr <- server.ListenAndServe()
}()

stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(stop)

select {
case err := <-serverErr:
if err != nil && err != http.ErrServerClosed {
log.Fatalf("serve: %v", err)
}
case sig := <-stop:
log.Printf("received %s, shutting down", sig)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("shutdown: %v", err)
}
if err := <-serverErr; err != nil && err != http.ErrServerClosed {
log.Fatalf("serve: %v", err)
}
}
}

Expand Down
99 changes: 99 additions & 0 deletions scripts/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env sh
set -eu

repo="blackdragoon26/Do-It"
install_dir="${DOIT_INSTALL_DIR:-$HOME/.local/bin}"
version="${DOIT_VERSION:-latest}"

os="$(uname -s | tr '[:upper:]' '[:lower:]')"
arch="$(uname -m)"

case "$arch" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
*) echo "unsupported architecture: $arch" >&2; exit 1 ;;
esac

case "$os" in
linux|darwin) archive_ext="tar.gz" ;;
*) echo "unsupported OS: $os" >&2; exit 1 ;;
esac

if [ "$version" = "latest" ]; then
base_url="https://github.com/$repo/releases/latest/download"
else
base_url="https://github.com/$repo/releases/download/$version"
fi

archive="Do-It_${os}_${arch}.${archive_ext}"
tmp_dir="$(mktemp -d 2>/dev/null || mktemp -d "${TMPDIR:-/tmp}/doit.XXXXXX")"
trap 'rm -rf "$tmp_dir"' EXIT INT TERM

download() {
url="$1"
output="$2"
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$url" -o "$output"
return
fi
if command -v wget >/dev/null 2>&1; then
wget -qO "$output" "$url"
return
fi
echo "curl or wget is required" >&2
exit 1
}

download_optional() {
url="$1"
output="$2"
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$url" -o "$output" >/dev/null 2>&1 && return 0
return 1
fi
if command -v wget >/dev/null 2>&1; then
wget -qO "$output" "$url" >/dev/null 2>&1 && return 0
return 1
fi
echo "curl or wget is required" >&2
exit 1
}
Comment on lines +47 to +60

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file around the referenced lines.
if [ -f scripts/install.sh ]; then
  wc -l scripts/install.sh
  sed -n '1,180p' scripts/install.sh | cat -n
fi

# Find where download_optional is used.
rg -n "download_optional|download\(" scripts/install.sh

Repository: blackdragoon26/Do-It

Length of output: 3633


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether releases always publish checksums.txt or if it is genuinely optional.
rg -n "checksums\.txt|sha256|release" .github scripts README* .

Repository: blackdragoon26/Do-It

Length of output: 4034


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the release workflow and installer docs to see whether checksums.txt is expected.
sed -n '1,220p' .github/workflows/release.yml | cat -n
printf '\n---- README excerpt ----\n'
sed -n '45,90p' README.md | cat -n

Repository: blackdragoon26/Do-It

Length of output: 2869


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for any GoReleaser config that could disable checksums or rename assets.
fd -a -H -t f '(.goreleaser.*|goreleaser.*)' .

Repository: blackdragoon26/Do-It

Length of output: 194


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect GoReleaser config to see whether checksums.txt is always emitted or can be missing.
wc -l .goreleaser.yaml
sed -n '1,260p' .goreleaser.yaml | cat -n

Repository: blackdragoon26/Do-It

Length of output: 1963


download_optional treats every fetch error as “checksums missing.” scripts/install.sh:47-52,88-91
A transient curl/wget failure now falls back to an unverified install; only skip verification for a real 404 and fail closed on transport/TLS/DNS errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.sh` around lines 47 - 60, The download_optional helper
currently treats any curl/wget failure as a missing checksum, so update its
callers and error handling to distinguish a real 404 from transport/TLS/DNS
failures. In download_optional and the checksum-fetch logic it feeds, inspect
the fetch result so only a 404 triggers the “checksums unavailable” fallback;
for any other nonzero exit, fail closed and stop the install. Use the
download_optional function and the checksum download path in scripts/install.sh
to locate the change.


verify_checksum() {
archive_path="$1"
checksums_path="$2"
archive_name="$(basename "$archive_path")"
expected="$(awk -v name="$archive_name" '$2 == name { print $1; found = 1 } END { if (!found) exit 1 }' "$checksums_path")" || {
echo "checksum for $archive_name not found" >&2
exit 1
}

if command -v sha256sum >/dev/null 2>&1; then
printf '%s %s\n' "$expected" "$archive_path" | sha256sum -c -
return
fi
if command -v shasum >/dev/null 2>&1; then
actual="$(shasum -a 256 "$archive_path" | awk '{ print $1 }')"
if [ "$actual" = "$expected" ]; then
return
fi
echo "$archive_name checksum mismatch" >&2
exit 1
fi
echo "sha256sum or shasum is required to verify downloads" >&2
exit 1
}

download "$base_url/$archive" "$tmp_dir/$archive"
if download_optional "$base_url/checksums.txt" "$tmp_dir/checksums.txt"; then
verify_checksum "$tmp_dir/$archive" "$tmp_dir/checksums.txt"
else
echo "checksums.txt not found for this release; installing without checksum verification" >&2
fi
Comment on lines +88 to +92

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== scripts/install.sh ==\n'
ast-grep outline scripts/install.sh --view expanded || true
printf '\n\n-- relevant lines --\n'
sed -n '1,140p' scripts/install.sh

printf '\n== release config candidates ==\n'
git ls-files | rg '(^|/)(\.goreleaser(\.ya?ml)?|goreleaser(\.ya?ml)?|release).*'

printf '\n== search for checksums.txt and DOIT_VERSION ==\n'
rg -n 'checksums\.txt|DOIT_VERSION|download_optional|verify_checksum' -S .

Repository: blackdragoon26/Do-It

Length of output: 3552


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== .goreleaser.yaml ==\n'
wc -l .goreleaser.yaml
sed -n '1,220p' .goreleaser.yaml

printf '\n== release workflow ==\n'
wc -l .github/workflows/release.yml
sed -n '1,220p' .github/workflows/release.yml

printf '\n== docs mention install script ==\n'
rg -n 'scripts/install\.sh|DOIT_VERSION|checksums\.txt|goreleaser' README.md .github . -g '!scripts/install.sh'

Repository: blackdragoon26/Do-It

Length of output: 3185


Fail closed when checksums.txt can’t be fetched.
.goreleaser.yaml always emits checksums.txt, so any fetch failure here should not silently skip integrity checking. Treat only a real 404 as the legacy fallback; transport errors should abort the install instead of proceeding unverified.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.sh` around lines 88 - 92, The checksum download fallback in
the install flow is too permissive and skips integrity verification on fetch
failures. Update the logic around download_optional in the install script so the
checksums.txt path fails closed for any transport or fetch error, and only
allows the legacy no-checksum path when the response is a real 404. Use the
existing verify_checksum and download_optional flow to distinguish not-found
from transient/network failures, and abort installation when checksums.txt
cannot be retrieved for any other reason.

tar -xzf "$tmp_dir/$archive" -C "$tmp_dir"

mkdir -p "$install_dir"
install "$tmp_dir/doit" "$install_dir/doit"

echo "Installed doit to $install_dir/doit"
echo "Run: $install_dir/doit"
Loading
Loading