Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0df599a
playwright e2e tests
AustinKelsay Feb 21, 2026
ac26496
fix test placeholder strings
AustinKelsay Feb 21, 2026
c579a3e
test: add Playwright E2E smoke suite and patch dev dep vulnerabilities
AustinKelsay Feb 21, 2026
d3c38a2
fix: move env admin gate before validation, fix Bearer token
AustinKelsay Feb 21, 2026
3a6cb0b
fix: reject empty RELAYS in /api/env updates
AustinKelsay Feb 24, 2026
156ce53
fix: expand 127.0.0.0/8 loopback filter, harden E2E cosigner, and cle…
AustinKelsay Feb 24, 2026
33e14cd
fix: lazy ENV_FILE_PATH eval, peer-list hook deps/a11y, CI audit out…
AustinKelsay Feb 24, 2026
813aed6
chore: harden e2e smoke flows and CI/env safeguards
AustinKelsay Feb 24, 2026
609544b
fix: tighten smoke test docs and cleanup guards
AustinKelsay Feb 24, 2026
657c79c
fix: harden relay req validation and test safety
AustinKelsay Feb 24, 2026
959edf4
fix: harden e2e cleanup, docs, and context handling
AustinKelsay Feb 24, 2026
6d73a98
fix: harden e2e smoke setup and route test safety
AustinKelsay Feb 25, 2026
944ec63
fix: harden smoke test harness and teardown behavior
AustinKelsay Feb 25, 2026
557e4a5
fix: tighten e2e cleanup and env test safeguards
AustinKelsay Feb 25, 2026
816eb0f
fix: pin Bun version in docker and CI workflows
AustinKelsay Feb 25, 2026
5f8713b
fix: harden e2e smoke tests and peer-list collapse behavior
AustinKelsay Feb 25, 2026
3f6481f
fix: harden relay limits and teardown safety
AustinKelsay Feb 25, 2026
b068104
fix: tighten e2e ui and loopback validation
AustinKelsay Feb 25, 2026
61bd400
test: clarify configure navigation e2e flow
AustinKelsay Feb 26, 2026
3b8c825
fix: address review findings across routes, docs, and e2e
AustinKelsay Feb 26, 2026
eb65308
fix: harden credential save and auth validation flows
AustinKelsay Feb 26, 2026
a4ebdcb
chore: remove Playwright e2e suite from repo
AustinKelsay Feb 26, 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
43 changes: 40 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
- name: Type check
run: bun run tsc --noEmit

- name: Run unit tests
run: bun run test:unit

- name: Build frontend
run: bun run build

Expand Down Expand Up @@ -71,16 +74,50 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Run security audit
run: |
bun audit || true # Don't fail on audit issues for now
audit_log="$(mktemp)"
last_exit=0
for attempt in 1 2 3; do
if bun audit >"$audit_log" 2>&1; then
cat "$audit_log"
rm -f "$audit_log"
exit 0
else
audit_exit=$?
last_exit=$audit_exit
last_attempt=$attempt
if [ "$attempt" -lt 3 ]; then
echo "bun audit failed (attempt $attempt), retrying..."
sleep 5
fi
fi
done

audit_output="$(cat "$audit_log")"
echo "bun audit failed after ${last_attempt:-3} attempts with exit code ${last_exit}"
if grep -Eiq 'network|registry|ENOTFOUND|ECONNREFUSED|EAI_AGAIN|ETIMEDOUT' "$audit_log"; then
echo "bun audit failed after retries due to network/registry error: $audit_output"
else
echo "bun audit failed after retries - vulnerabilities detected: $audit_output"
fi
rm -f "$audit_log"
exit 1

- name: Check for secrets
uses: trufflesecurity/trufflehog@main
# Pinned to immutable commit (v3.93.4) for supply-chain safety.
uses: trufflesecurity/trufflehog@7c0734f987ad0bb30ee8da210773b800ee2016d3
with:
path: ./
extra_args: --debug --only-verified
continue-on-error: true

Comment thread
AustinKelsay marked this conversation as resolved.
docker:
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ jobs:
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "version_number=${NEW_VERSION#v}" >> $GITHUB_OUTPUT

- name: Type check
run: bun run tsc --noEmit

- name: Run backend tests
run: bun run test:unit

- name: Build application
run: bun run build

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ data/.session-secret
test-*.sh
debug-*.js
verify-*.md
.DS_Store
test-results/

# LLM files
.claude
114 changes: 57 additions & 57 deletions bun.lock

Large diffs are not rendered by default.

34 changes: 21 additions & 13 deletions frontend/components/ui/peer-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ const PeerList: React.FC<PeerListProps> = ({
window.removeEventListener('peerStatusUpdate', handlePeerUpdate as EventListener);
window.removeEventListener('peerPingUpdate', handlePeerUpdate as EventListener);
};
}, [isSignerRunning]);
}, [authHeaders, isSignerRunning]);

// Ping individual peer
const handlePingPeer = useCallback(async (peerPubkey: string) => {
Expand Down Expand Up @@ -434,7 +434,7 @@ const PeerList: React.FC<PeerListProps> = ({
return newSet;
});
}
}, [isSignerRunning]);
}, [authHeaders, isSignerRunning]);

const updatePeerPolicy = useCallback(async (peer: PeerStatus, changes: { allowSend?: boolean; allowReceive?: boolean }) => {
if (!isSignerRunning || disabled) {
Expand Down Expand Up @@ -525,7 +525,7 @@ const PeerList: React.FC<PeerListProps> = ({
return;
}
try {
const response = await fetch('/api/peers/ping', {
await fetch('/api/peers/ping', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand All @@ -534,14 +534,12 @@ const PeerList: React.FC<PeerListProps> = ({
body: JSON.stringify({ target: 'all' })
});

const result = await response.json();

// Refresh peer list after pinging all
await fetchPeers();
} catch (error) {
console.warn('[PeerList] Ping all failed:', error);
}
}, [isSignerRunning, peers.length, fetchPeers]);
}, [authHeaders, isSignerRunning, peers.length, fetchPeers]);

// Enhanced refresh that includes pinging
const handleRefresh = useCallback(async () => {
Expand Down Expand Up @@ -597,6 +595,7 @@ const PeerList: React.FC<PeerListProps> = ({
className="flex flex-col sm:flex-row sm:items-center justify-between bg-gray-800/50 p-2.5 rounded cursor-pointer hover:bg-gray-800/70 transition-colors gap-2 sm:gap-0"
onClick={handleToggle}
role="button"
aria-expanded={isExpanded}
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
Expand All @@ -611,11 +610,20 @@ const PeerList: React.FC<PeerListProps> = ({
<ChevronDown className="h-4 w-4 text-blue-400 flex-shrink-0" />
}
<span className="text-blue-200 text-sm font-medium select-none">Peer List</span>
<div onClick={e => e.stopPropagation()}>
<div onClick={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()}>
<Tooltip
position="right"
width="w-64"
trigger={<HelpCircle size={16} className="text-blue-400 cursor-pointer" />}
focusable
trigger={(
<button
type="button"
aria-label="Peer list help"
className="inline-flex items-center text-blue-400 cursor-pointer"
>
<HelpCircle size={16} />
</button>
)}
content={
<p>Shows the signing peers in your FROSTR group with online/offline status and ping latency. Use the refresh button to ping all peers and update their status.</p>
}
Expand Down Expand Up @@ -654,7 +662,7 @@ const PeerList: React.FC<PeerListProps> = ({
)}
</div>
</div>
<div onClick={e => e.stopPropagation()} className="flex-shrink-0">
<div onClick={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()} className="flex-shrink-0">
{actions}
</div>
</div>
Expand All @@ -665,7 +673,9 @@ const PeerList: React.FC<PeerListProps> = ({
"transition-all duration-300 ease-in-out overflow-hidden",
isExpanded ? "max-h-[400px] opacity-100" : "max-h-0 opacity-0"
)}
aria-hidden={!isExpanded}
>
Comment thread
AustinKelsay marked this conversation as resolved.
{isExpanded && (
<div className="bg-gray-900/30 rounded border border-gray-800/30 p-4 space-y-4">
{isLoading ? (
<div className="flex items-center justify-center py-8">
Expand Down Expand Up @@ -770,10 +780,7 @@ const PeerList: React.FC<PeerListProps> = ({
</div>
<div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-gray-400">
<span className="whitespace-nowrap">Policy: out {outboundPolicy.statusLabel}, in {inboundPolicy.statusLabel}</span>
<Badge
variant={policyBadgeVariant as any}
className="text-xs px-2 py-0.5 whitespace-nowrap"
>
<Badge variant={policyBadgeVariant} className="text-xs px-2 py-0.5 whitespace-nowrap">
{policyBadgeLabel}
</Badge>
</div>
Expand Down Expand Up @@ -896,6 +903,7 @@ const PeerList: React.FC<PeerListProps> = ({
</div>
)}
</div>
)}
</div>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions frontend/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export interface UpdateInfo {
updateAvailable: boolean;
releaseUrl?: string;
checkedAt?: string;
source?: 'github-release' | 'github-tags';
error?: string;
}

Expand Down
Loading