89 Commits

Author SHA1 Message Date
Renovate Bot
2d8dcbca22 Update https://git.quad4.io/actions/setup-go digest to 40f1582
All checks were successful
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 9m24s
2025-12-31 00:01:32 +00:00
db82c15c51 Auto-update SBOM [skip ci] 2025-12-30 03:41:17 +00:00
ec38a69c57 Add mkdir command to create frontend_dist directory in desktop build tasks
All checks were successful
CI / scan-backend (push) Successful in 11s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m29s
CI / build-frontend (push) Successful in 9m40s
CI / build-backend (push) Successful in 19s
2025-12-29 21:31:20 -06:00
ae08e4dc5f Refactor build workflow
All checks were successful
CI / scan-backend (push) Successful in 10s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m25s
CI / build-frontend (push) Successful in 9m40s
CI / build-backend (push) Successful in 9m27s
2025-12-29 21:18:30 -06:00
cd3d9862c3 Update download-artifact action version in build workflow to v3.0.2
Some checks failed
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 18s
CI / build-frontend (push) Successful in 42s
CI / build-backend (push) Has been cancelled
CI / scan-backend (push) Has been cancelled
2025-12-29 21:15:06 -06:00
0f383d7f44 Update README 2025-12-29 17:36:44 -06:00
1180804025 Add Podman tasks to Taskfile.yml for building and running containers 2025-12-29 17:34:32 -06:00
c22e1af86f Update CACHE_VERSION to 1.5.1 in service worker
All checks were successful
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 22s
CI / build-frontend (push) Successful in 43s
CI / scan-backend (push) Successful in 9m22s
CI / build-backend (push) Successful in 19s
2025-12-29 16:42:30 -06:00
09c62bed71 Add flake.lock and update flake.nix with new dependencies and hashes 2025-12-29 16:42:24 -06:00
c780fe040a Update README 2025-12-29 16:36:51 -06:00
1e521b0c59 Add task to build desktop application for Linux in Taskfile.yml 2025-12-29 16:35:42 -06:00
832afe7b90 Add build and release workflow configuration 2025-12-29 16:35:37 -06:00
6d0069a8d3 Add flake.nix 2025-12-29 16:30:53 -06:00
12e3cf9354 Fix SBOM workflow by adding ref parameter for checkout and ensuring push to master branch
All checks were successful
CI / scan-backend (push) Successful in 12s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m22s
CI / build-frontend (push) Successful in 9m37s
CI / build-backend (push) Successful in 9m28s
2025-12-29 16:12:46 -06:00
7ba1cfe6f7 Update SBOM workflow to trigger on version tags instead of branches
Some checks failed
CI / scan-backend (push) Successful in 11s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m23s
CI / build-frontend (push) Successful in 9m38s
Build and Publish Docker Image / build (push) Successful in 10m10s
CI / build-backend (push) Successful in 9m27s
Generate SBOM / generate-sbom (push) Failing after 9m28s
2025-12-29 14:28:22 -06:00
15d697c946 Auto-update SBOM [skip ci] 2025-12-29 20:25:57 +00:00
a8a4405946 1.5.1
All checks were successful
CI / scan-backend (push) Successful in 17s
Generate SBOM / generate-sbom (push) Successful in 23s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m23s
CI / build-frontend (push) Successful in 9m38s
CI / build-backend (push) Successful in 24s
2025-12-29 14:25:31 -06:00
2ddd0bf9fd 1.5.1 2025-12-29 14:25:24 -06:00
c3e10b3945 Auto-update SBOM [skip ci] 2025-12-29 20:15:06 +00:00
6da7b31269 Add HOST environment variable to Dockerfile for host binding
All checks were successful
CI / scan-backend (push) Successful in 17s
Generate SBOM / generate-sbom (push) Successful in 36s
CI / build-frontend (push) Successful in 9m37s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m29s
CI / build-backend (push) Successful in 9m27s
2025-12-29 14:14:25 -06:00
4b553d67d4 Update main.go to allow HOST environment variable for host binding and improve error handling in API response. Update app.go to enforce stricter file permissions and ensure valid file paths when loading files. 2025-12-29 14:14:20 -06:00
3b5807a480 Auto-update SBOM [skip ci] 2025-12-29 19:56:07 +00:00
e6c0387cdd Update Dockerfile path in CI workflow to use ./docker/Dockerfile
All checks were successful
CI / scan-backend (push) Successful in 22s
Generate SBOM / generate-sbom (push) Successful in 25s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m23s
CI / build-frontend (push) Successful in 9m38s
CI / build-backend (push) Successful in 26s
2025-12-29 13:55:39 -06:00
ce65f05bd4 Auto-update SBOM [skip ci] 2025-12-29 19:52:12 +00:00
3190c6f119 Update README.md
All checks were successful
CI / scan-backend (push) Successful in 19s
Generate SBOM / generate-sbom (push) Successful in 25s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m30s
CI / build-frontend (push) Successful in 9m36s
CI / build-backend (push) Successful in 28s
2025-12-29 13:51:47 -06:00
7a725a505f Change default host binding from '0.0.0.0' to '127.0.0.1' in main.go 2025-12-29 13:51:09 -06:00
6a1667b34d Auto-update SBOM [skip ci] 2025-12-29 19:38:07 +00:00
2f1bf6a05a Fix output format for CycloneDX in SBOM generation step of CI workflow
All checks were successful
CI / scan-backend (push) Successful in 22s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 38s
Generate SBOM / generate-sbom (push) Successful in 43s
CI / build-frontend (push) Successful in 49s
CI / build-backend (push) Successful in 22s
2025-12-29 13:37:17 -06:00
3662bda009 Specify version '3.46.3' for Setup Task action in CI workflow
Some checks failed
CI / scan-backend (push) Successful in 20s
Generate SBOM / generate-sbom (push) Failing after 23s
CI / build-backend (push) Has been cancelled
CI / build-frontend (push) Has been cancelled
OSV-Scanner Scheduled Scan / scan-scheduled (push) Has been cancelled
2025-12-29 13:35:29 -06:00
0757ca64f9 Update CI workflow by adding linting step to frontend
Some checks failed
Generate SBOM / generate-sbom (push) Failing after 13s
CI / scan-backend (push) Successful in 15s
CI / build-frontend (push) Has been cancelled
CI / build-backend (push) Has been cancelled
OSV-Scanner Scheduled Scan / scan-scheduled (push) Has been cancelled
2025-12-29 13:32:46 -06:00
d2856b27a8 Update
Some checks failed
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 20s
CI / build-frontend (push) Successful in 40s
Generate SBOM / generate-sbom (push) Has been cancelled
CI / build-backend (push) Successful in 21s
CI / lint-backend (push) Successful in 9m25s
2025-12-29 13:30:05 -06:00
1532bcae31 Update CI workflow to specify version for Setup Task action 2025-12-29 13:29:59 -06:00
c9627a71ea Add GitHub Action workflow to generate Software Bill of Materials (SBOM) using Trivy
Some checks failed
Generate SBOM / generate-sbom (push) Failing after 48s
CI / build-frontend (push) Failing after 4m44s
CI / build-backend (push) Has been skipped
CI / lint-backend (push) Successful in 12s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Has been cancelled
2025-12-29 13:22:20 -06:00
8ed205375b Remove duplicate import
Some checks failed
CI / lint-backend (push) Successful in 24s
CI / build-frontend (push) Failing after 4m41s
CI / build-backend (push) Has been skipped
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m25s
2025-12-29 13:11:17 -06:00
0bf731df66 Update CHANGELOG.md
Some checks failed
CI / build-frontend (push) Failing after 14s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 16s
CI / build-backend (push) Has been cancelled
CI / lint-backend (push) Has been cancelled
2025-12-29 13:10:15 -06:00
2064760ea9 Add new tasks to Taskfile.yml for building frontend and backend, setting up development environment, and installing dependencies for CI. 2025-12-29 13:08:15 -06:00
06300f08e3 Update CI workflow by integrating Task 2025-12-29 13:08:08 -06:00
c463eb1d94 Refactor IdentityGraph component to normalize links and improve data handling. Added normalizeLinks function to ensure link types and strengths are validated against predefined lists. 2025-12-29 13:07:55 -06:00
add7f6e530 Update SECURITY.md to include PNPM in vulnerability scanning and add SAST tools for Go and JavaScript code. 2025-12-29 12:58:48 -06:00
7a3b3ca054 Add eslint-plugin-security to ESLint configuration and update package.json and pnpm-lock.yaml 2025-12-29 12:58:37 -06:00
540f9712db Add cookie version override in package.json and pnpm-lock.yaml
Some checks failed
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 14s
CI / build-frontend (push) Successful in 9m37s
CI / build-backend (push) Has been cancelled
2025-12-29 12:53:54 -06:00
6ac2968b73 Update CI workflow to use pnpm for dependency management and upgrade Go version to 1.25.5
All checks were successful
CI / build-frontend (push) Successful in 39s
CI / build-backend (push) Successful in 20s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m25s
2025-12-29 12:49:44 -06:00
217b10b1fd Update CHANGELOG.md for version 1.5.0
Some checks failed
CI / build-frontend (push) Failing after 3s
CI / build-backend (push) Has been skipped
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 16s
2025-12-29 12:48:32 -06:00
3b6331faea Remove 2025-12-29 12:43:02 -06:00
8eb12a7087 Remove redundant line 2025-12-29 12:42:54 -06:00
5fac643e86 Update IdentityGraph component by adding canvasElement for improved touch event handling and updating event listeners for better state management. 2025-12-29 12:42:37 -06:00
d862b1d222 Update ESLint configuration to add readonly globals for Element and EventListener 2025-12-29 12:28:04 -06:00
46bc6bdb22 Add SECURITY.md 2025-12-29 12:27:56 -06:00
0b90005bf7 refactor IdentityGraph component to improve touch event handling and state management with IndexedDB 2025-12-29 12:27:30 -06:00
bab846cd83 Refactor layout component to use props for children and update event handling for improved readability and functionality. 2025-12-29 12:12:05 -06:00
59030ba2a3 Refactor IdentityGraph component to utilize centralized constants and implement undo/redo functionality with IndexedDB for state management. 2025-12-29 12:12:00 -06:00
9468010981 Improve README 2025-12-29 12:11:41 -06:00
38887b1de2 Remove 2025-12-29 12:11:25 -06:00
2c65a17b12 Remove 2025-12-29 12:11:19 -06:00
c1c823d2b1 Remove 2025-12-29 12:11:11 -06:00
9e7a9f6d2c Add constants and types for database, relationships, and node types in constants.ts 2025-12-29 12:11:07 -06:00
a3a78ae117 Remove unnecessary newline at the end of inject-sw-version.js for cleaner code. 2025-12-29 12:11:00 -06:00
51ce1cbc40 Update build script to use pnpm instead of npm for building the app 2025-12-29 12:10:55 -06:00
1202652e93 Add compiler options in svelte.config.js to manage runes for external dependencies 2025-12-29 12:10:47 -06:00
3b9b8e0a65 Refactor ESLint configuration by formatting the ignores array for improved readability. 2025-12-29 12:10:40 -06:00
44ccc672fc Update package version to 1.5.0, add author and license information, and update dependencies in package.json. Introduce pnpm-lock.yaml for dependency management. Update service worker cache version to 1.5.0. 2025-12-29 12:10:27 -06:00
625dcc11f8 Fix formatting in svelte.config.js by adding a missing comma and ensuring proper structure. 2025-12-29 11:33:57 -06:00
62f3f34e10 Update frontend package manager from npm to pnpm in wails.json 2025-12-29 11:33:51 -06:00
aad59ffe43 Fix indentation in renovate.json schema declaration 2025-12-29 11:33:42 -06:00
4b20bf540e Update Docker workflow 2025-12-29 11:33:36 -06:00
dd5e24ae26 Remove 2025-12-29 11:33:21 -06:00
bc20b06fe1 Remove package-lock 2025-12-29 11:33:11 -06:00
e7801735fa Update Go version to 1.25.5 2025-12-29 11:33:03 -06:00
fbbb6a5e9c Update LICENSE 2025-12-29 11:32:46 -06:00
ebdbd02599 Move Dockerfile 2025-12-29 11:32:19 -06:00
312fe5e746 Replace Makefile with Taskfile 2025-12-29 11:31:58 -06:00
469b59a561 Add IndexedDB support for graph and settings storage
- Implemented functions to initialize and interact with IndexedDB for storing graph data and user settings.
- Migrated existing localStorage data to IndexedDB on application load.
- Updated save and load functions to utilize IndexedDB instead of localStorage.
- Enhanced graph rendering with curved paths for links between nodes.
- Improved theme management by saving user preferences in IndexedDB.
2025-12-29 11:30:49 -06:00
bc5b12b23c Update workflow hashes
All checks were successful
CI / build-frontend (push) Successful in 38s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 9m26s
CI / build-backend (push) Successful in 9m33s
2025-12-29 00:03:21 -06:00
5f5de2272b Update Gitea workflows to use custom action URLs for checkout, setup-node, setup-go, and other actions
All checks were successful
CI / build-frontend (push) Successful in 53s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 31s
CI / build-backend (push) Successful in 20s
2025-12-28 21:08:07 -06:00
7b4598c5ca Update Gitea workflow to use custom action URLs for checkout and setup-go 2025-12-28 21:07:46 -06:00
ab2dd4e4ed Remove renovate workflow 2025-12-28 21:07:41 -06:00
ivan
e366ba8f1b Merge pull request 'Update ghcr.io/renovatebot/renovate Docker tag to v42.66.11' (#5) from renovate/ghcr.io-renovatebot-renovate-42.x into master
Some checks failed
renovate / renovate (push) Failing after 10s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 29s
CI / build-frontend (push) Successful in 9m37s
CI / build-backend (push) Successful in 21s
Reviewed-on: #5
2025-12-29 00:21:44 +00:00
Renovate Bot
6971796c00 Update ghcr.io/renovatebot/renovate Docker tag to v42.66.11
All checks were successful
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 19s
2025-12-29 00:02:10 +00:00
ivan
d85d960e3d Merge pull request 'Update ghcr.io/renovatebot/renovate Docker tag to v42' (#4) from renovate/ghcr.io-renovatebot-renovate-42.x into master
Some checks failed
renovate / renovate (push) Failing after 1m14s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 10m0s
CI / build-frontend (push) Successful in 10m19s
CI / build-backend (push) Successful in 1m57s
Reviewed-on: #4
2025-12-28 05:30:32 +00:00
Renovate Bot
d99fce9b24 Update ghcr.io/renovatebot/renovate Docker tag to v42
All checks were successful
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 18s
2025-12-28 00:00:48 +00:00
ivan
d770914aae Merge pull request 'Update ghcr.io/renovatebot/renovate Docker tag to v37.440.7' (#2) from renovate/ghcr.io-renovatebot-renovate-37.x into master
Some checks failed
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 15s
renovate / renovate (push) Failing after 14s
CI / build-frontend (push) Successful in 9m32s
CI / build-backend (push) Successful in 9m27s
Reviewed-on: #2
2025-12-27 22:44:20 +00:00
Renovate Bot
02d745f9ae Update ghcr.io/renovatebot/renovate Docker tag to v37.440.7
All checks were successful
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 9m45s
2025-12-27 22:29:35 +00:00
ivan
5c7c6c4ca5 Merge pull request 'Configure Renovate' (#1) from renovate/configure into master
Some checks failed
CI / build-frontend (push) Successful in 41s
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 18s
CI / build-backend (push) Successful in 24s
renovate / renovate (push) Failing after 19s
Reviewed-on: #1
2025-12-27 20:52:32 +00:00
Renovate Bot
e6bc79ec27 Add renovate.json
All checks were successful
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 23s
2025-12-27 20:29:30 +00:00
03f0c71aae Add Renovate workflow for automated dependency management
Some checks failed
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 23s
CI / build-frontend (push) Successful in 46s
CI / build-backend (push) Successful in 28s
renovate / renovate (push) Failing after 11s
2025-12-27 14:28:38 -06:00
4923619b51 Update CI workflows and OSV scan script for improved functionality
All checks were successful
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 21s
CI / build-frontend (push) Successful in 39s
CI / build-backend (push) Successful in 21s
- Updated the 'checkout' action to version 4 for consistency across workflows.
- Added a 'Setup Go' step to initialize the Go environment using the latest action version.
- Modified the OSV scan script to generalize vulnerability reporting, removing specific severity checks for a broader output.
2025-12-27 12:46:16 -06:00
7e75064ae5 Update CI workflows to use specific action versions
All checks were successful
OSV-Scanner Scheduled Scan / scan-scheduled (push) Successful in 17s
CI / build-frontend (push) Successful in 53s
CI / build-backend (push) Successful in 29s
- Updated the 'checkout' action to version 4.3.1 across multiple workflows for consistency.
- Updated various actions in the Docker, npm publish, and OSV workflows to their respective latest versions for improved functionality and security.
2025-12-26 21:53:14 -06:00
7c13aee0a7 Update package script to include versioning for build process
- Modified the 'package' script in package.json to set the VITE_APP_VERSION environment variable using the current package version, ensuring the build process incorporates the correct version information.
2025-12-26 21:53:07 -06:00
d5b37ed53f Update Makefile to include new 'package' target
- Added a 'package' target that depends on the 'build' target to streamline the build process.
- Updated the .PHONY section to include the new 'package' target for better organization.
2025-12-26 21:52:59 -06:00
41 changed files with 26025 additions and 4917 deletions

108
.gitea/workflows/build.yml Normal file
View File

@@ -0,0 +1,108 @@
name: Build and Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., v1.0.0)'
required: true
type: string
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: https://git.quad4.io/actions/checkout@a5b3063b1edaa6ba4911c8a1b1d5e1656fba3ea5 # v4
with:
fetch-depth: 0
- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Setup Node.js
uses: https://git.quad4.io/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: pnpm
- name: Setup Task
uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1
with:
version: '3.46.3'
- name: Setup environment
run: task setup
- name: Install dependencies
run: task install:ci
- name: Build frontend
run: task build:frontend
- name: Setup Go
uses: https://git.quad4.io/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: '1.25.5'
- name: Build server binaries
run: |
task build:backend
task build-linux-amd64
task build-windows-amd64
- name: Build desktop Linux
run: task desktop-linux
- name: Build desktop Windows
run: task desktop-windows
- name: Prepare release assets
run: |
mkdir -p release-assets
cp bin/linking-tool-linux-amd64 release-assets/
cp bin/linking-tool-windows-amd64.exe release-assets/
if [ -f desktop/build/bin/linking-tool ]; then
cp desktop/build/bin/linking-tool release-assets/linking-tool-desktop-linux-amd64
fi
if [ -f desktop/build/bin/linking-tool.exe ]; then
cp desktop/build/bin/linking-tool.exe release-assets/linking-tool-desktop-windows-amd64.exe
fi
- name: Download SBOM
run: |
git fetch origin master:master || true
git checkout master -- sbom/ || git checkout ${{ github.sha }} -- sbom/ || true
if [ -d sbom ]; then
cp sbom/*.json release-assets/ || true
fi
- name: Create Release
uses: https://git.quad4.io/actions/gitea-release-action@4875285c0950474efb7ca2df55233c51333eeb74 # v1
with:
api_url: ${{ secrets.GITEA_API_URL }}
gitea_token: ${{ secrets.GITEA_TOKEN }}
title: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.version }}
body: |
Release ${{ steps.version.outputs.version }}
## Assets
- Server binaries (Linux AMD64, Windows AMD64)
- Desktop applications (Linux AMD64, Windows AMD64)
- SBOM files
files: release-assets/*
draft: false
prerelease: false

View File

@@ -11,40 +11,62 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
uses: https://git.quad4.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
uses: https://git.quad4.io/actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: npm
cache: pnpm
- name: Setup Task
uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1
with:
version: '3.46.3'
- name: Setup environment
run: task setup
- name: Install dependencies
run: npm ci
run: task install:ci
- name: Lint
run: task lint
- name: Frontend checks
run: bash scripts/check.sh
run: task check
- name: Build frontend
run: bash scripts/build.sh
run: task build:frontend
- name: Upload frontend assets
uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
uses: https://git.quad4.io/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
with:
name: frontend-build
path: build/
build-backend:
scan-backend:
runs-on: ubuntu-latest
needs: build-frontend
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
uses: https://git.quad4.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Go
uses: https://git.quad4.io/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: '1.25.5'
- name: Run gosec security scan
uses: https://git.quad4.io/actions/gosec@424fc4cd9c82ea0fd6bee9cd49c2db2c3cc0c93f # v2.22.11
build-backend:
runs-on: ubuntu-latest
needs: [build-frontend, scan-backend]
steps:
- name: Checkout
uses: https://git.quad4.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Download frontend assets
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
uses: https://git.quad4.io/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
with:
name: frontend-build
path: build/
- name: Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
uses: https://git.quad4.io/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: '1.25.4'
go-version: '1.25.5'
- name: Setup Task
uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1
with:
version: '3.46.3'
- name: Build backend
run: |
mkdir -p bin
CGO_ENABLED=0 go build -ldflags="-s -w" -o bin/linking-tool main.go
run: task build:backend

View File

@@ -22,18 +22,18 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744
uses: https://git.quad4.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
uses: https://git.quad4.io/actions/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
with:
platforms: amd64,arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435
uses: https://git.quad4.io/actions/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to the Container registry
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
uses: https://git.quad4.io/actions/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
@@ -41,7 +41,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f
uses: https://git.quad4.io/actions/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
@@ -54,10 +54,10 @@ jobs:
- name: Build and push Docker image
id: build
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25
uses: https://git.quad4.io/actions/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
file: ./Dockerfile
file: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}

View File

@@ -1,36 +0,0 @@
name: Publish NPM Package
on:
workflow_dispatch:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install dependencies
run: npm ci --registry=https://registry.npmjs.org/
- name: Package
run: make package
- name: Configure npm for publishing
uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://git.quad4.io/api/packages/quad4-software/npm/'
- name: Publish
run: npm publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -14,7 +14,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: https://git.quad4.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Go
uses: https://git.quad4.io/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: 'go.mod'
- name: OSV scan
run: bash scripts/osv_scan.sh

View File

@@ -14,7 +14,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: https://git.quad4.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Go
uses: https://git.quad4.io/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: 'go.mod'
- name: OSV scan
run: bash scripts/osv_scan.sh

63
.gitea/workflows/sbom.yml Normal file
View File

@@ -0,0 +1,63 @@
name: Generate SBOM
on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
generate-sbom:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: https://git.quad4.io/actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
ref: ${{ github.ref }}
- name: Setup Node.js
uses: https://git.quad4.io/actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22
cache: pnpm
- name: Setup Go
uses: https://git.quad4.io/actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version: '1.25.5'
- name: Setup Task
uses: https://git.quad4.io/actions/setup-task@0ab1b2a65bc55236a3bc64cde78f80e20e8885c2 # v1
with:
version: '3.46.3'
- name: Setup environment
run: task setup
- name: Install dependencies
run: task install:ci
- name: Download Trivy
run: |
curl -L -o /tmp/trivy.deb https://git.quad4.io/Quad4-Extra/assets/raw/commit/90fdcea1bb71d91df2de6ff2e3897f278413f300/bin/trivy_0.68.2_Linux-64bit.deb
sudo dpkg -i /tmp/trivy.deb || sudo apt-get install -f -y
- name: Generate SBOM
run: |
mkdir -p sbom
trivy fs --format spdx-json --include-dev-deps --output sbom/sbom.spdx.json .
trivy fs --format cyclonedx --include-dev-deps --output sbom/sbom.cyclonedx.json .
- name: Commit and Push Changes
run: |
git config --global user.name "Gitea Action"
git config --global user.email "actions@noreply.quad4.io"
git remote set-url origin https://${{ secrets.GITEA_TOKEN }}@git.quad4.io/${{ github.repository }}.git
git fetch origin master
git checkout master
git add sbom/
git diff --quiet && git diff --staged --quiet || (git commit -m "Auto-update SBOM [skip ci]" && git push origin master)
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}

57
CHANGELOG.md Normal file
View File

@@ -0,0 +1,57 @@
# Changelog
## 1.5.1 - 2025-12-29
### Features
- Added HOST environment variable support for configuring server host binding
### Security
- Fixed unhandled error in HTTP response writing (G104)
- Fixed file write permissions to use more restrictive 0600 instead of 0644 (G306)
- Fixed potential file inclusion vulnerability by adding path validation in file operations (G304)
### Docker
- Added HOST environment variable to Dockerfile (defaults to 0.0.0.0, make sure to set it properly in production)
## 1.5.0 - 2025-12-29
### Features
- Move to IndexedDB for saving graph data (from localStorage)
- Add multiple links support between nodes.
- Increase undo/redo history to 100 steps.
- Move undo/redo operations to IndexedDB instead of memory.
- Mass selection improvements (moving and linking multiple nodes at once).
- Codebase refactor to use Svelte 5 Runes.
- Mobile improvements
- Added SBOM generation, see `/sbom/` for the generated SBOMs.
### Dependency Updates
- `@sveltejs/kit`: ^2.49.1 -> ^2.49.2
- `@typescript-eslint/eslint-plugin`: ^8.50.1 -> ^8.51.0
- `@typescript-eslint/parser`: ^8.50.1 -> ^8.51.0
- `svelte`: ^5.45.6 -> ^5.46.1
- `svelte-check`: ^4.3.4 -> ^4.3.5
- `vite`: ^7.2.6 -> ^7.3.0
- Added `eslint-plugin-security`: ^3.0.1
### Major Codebase Changes
- Moved from `npm` to `pnpm`
- Updated license from `MIT` to `BSD-3-Clause`
- Moved from `Makefile` to `Taskfile`
- Codebase organization and structure changes
### CI/CD Updates
- Updated CI workflows to use `task` commands instead of bash scripts
- Added gosec security scanning to backend build pipeline
### Security
- Overrode `cookie` package to latest version (1.1.1) due to low severity vulnerability in default version.

View File

@@ -1,41 +0,0 @@
FROM cgr.dev/chainguard/node:latest-dev AS node-builder
WORKDIR /app
COPY --chown=node:node package.json package-lock.json ./
RUN npm ci
COPY --chown=node:node . .
RUN npm run build
FROM golang:alpine AS builder
# Install dependencies for Wails on Alpine
# Added webkit2gtk-4.1-dev which is the modern package name in Alpine
RUN apk add --no-cache \
git \
make \
gcc \
musl-dev \
pkgconfig \
gtk+3.0-dev \
webkit2gtk-4.1-dev \
curl
# Install Wails
RUN go install github.com/wailsapp/wails/v2/cmd/wails@latest
ENV PATH=$PATH:/root/go/bin
WORKDIR /app
COPY . .
COPY --from=node-builder /app/build ./build
# Build the Go server
RUN mkdir -p bin && \
CGO_ENABLED=0 go build -ldflags="-s -w" -o bin/linking-tool main.go
# Build desktop apps
RUN mkdir -p desktop/frontend_dist && \
cp -r build/* desktop/frontend_dist/ && \
cd desktop && wails build -s -platform linux/amd64 -o linking-tool-linux
FROM scratch
COPY --from=builder /app/bin /bin
COPY --from=builder /app/desktop/build/bin /desktop-bin

38
LICENSE
View File

@@ -1,22 +1,28 @@
MIT License
BSD 3-Clause License
Copyright (c) 2025 Quad4.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,92 +0,0 @@
BINARY_NAME=linking-tool
BUILD_DIR=bin
.PHONY: help install dev build preview check lint format clean docker-build docker-run docker-builder release build-linux-amd64 build-linux-arm64 build-linux-armv6 build-linux-armv7 build-windows-amd64 build-darwin-amd64 build-darwin-arm64 build-freebsd-amd64 desktop-build desktop-windows desktop-darwin desktop-dev
help:
@echo 'Usage: make [target]'
@echo ''
@echo 'Available targets:'
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-20s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
dev:
npm install
npm run dev
build:
npm install
npm run build
mkdir -p $(BUILD_DIR)
CGO_ENABLED=0 go build -ldflags="-s -w" -o $(BUILD_DIR)/$(BINARY_NAME) main.go
release: build
mkdir -p $(BUILD_DIR)
@$(MAKE) build-linux-amd64
@$(MAKE) build-linux-arm64
@$(MAKE) build-linux-armv6
@$(MAKE) build-linux-armv7
@$(MAKE) build-windows-amd64
@$(MAKE) build-darwin-amd64
@$(MAKE) build-darwin-arm64
@$(MAKE) build-freebsd-amd64
build-linux-amd64:
GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 main.go
build-linux-arm64:
GOOS=linux GOARCH=arm64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-linux-arm64 main.go
build-linux-armv6:
GOOS=linux GOARCH=arm GOARM=6 go build -o $(BUILD_DIR)/$(BINARY_NAME)-linux-armv6 main.go
build-linux-armv7:
GOOS=linux GOARCH=arm GOARM=7 go build -o $(BUILD_DIR)/$(BINARY_NAME)-linux-armv7 main.go
build-windows-amd64:
GOOS=windows GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-windows-amd64.exe main.go
build-darwin-amd64:
GOOS=darwin GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-amd64 main.go
build-darwin-arm64:
GOOS=darwin GOARCH=arm64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-arm64 main.go
build-freebsd-amd64:
GOOS=freebsd GOARCH=amd64 go build -o $(BUILD_DIR)/$(BINARY_NAME)-freebsd-amd64 main.go
docker-build:
docker build -t $(BINARY_NAME) .
docker-run:
docker run -p 8080:8080 $(BINARY_NAME)
docker-builder:
docker build -f Dockerfile.build -t $(BINARY_NAME)-build .
docker create --name $(BINARY_NAME)-temp $(BINARY_NAME)-build
mkdir -p $(BUILD_DIR)
docker cp $(BINARY_NAME)-temp:/bin/. $(BUILD_DIR)/
docker cp $(BINARY_NAME)-temp:/desktop-bin/. $(BUILD_DIR)/
docker rm $(BINARY_NAME)-temp
desktop-build: build
rm -rf desktop/frontend_dist/*
cp -r build/* desktop/frontend_dist/
cd desktop && wails build -s
desktop-windows: build
rm -rf desktop/frontend_dist/*
cp -r build/* desktop/frontend_dist/
cd desktop && wails build -s -platform windows/amd64
desktop-darwin: build
rm -rf desktop/frontend_dist/*
cp -r build/* desktop/frontend_dist/
cd desktop && wails build -s -platform darwin/universal
desktop-dev: build
rm -rf desktop/frontend_dist/*
cp -r build/* desktop/frontend_dist/
cd desktop && wails dev
clean:
rm -rf .svelte-kit build node_modules/.vite dist package linking-tool tmp $(BUILD_DIR)

141
README.md
View File

@@ -1,87 +1,142 @@
# Quad4 Linking Tool
A client-side web linking tool for mapping relationships between entities.
A web linking tool for mapping relationships between entities.
<img src="showcase/linkingtool.png" alt="showcase image" width="900">
## Features
Desktop apps for Windows, macOS, and Linux are coming soon...
- Interactive graph visualization
- Multiple entity types (person, email, phone, address, domain, org, IP, social)
- Auto-save to localStorage
- Import/Export JSON
- Share link via base64 for smaller graphs
- Undo/Redo support
- PWA support (installable, offline-capable)
- Desktop App support (via Wails)
- Single Binary Web Server (via Go)
- Mobile support
## Quick Start
## Self-Hosting
### Using the Binary
### Go Binary
The easiest way to self-host is using the single binary:
1. Build the binary:
```sh
./linking-tool --port 8080
task build
```
### NPM
2. Run the server:
```sh
npm config set @quad4:registry https://git.quad4.io/api/packages/quad4-software/npm/
npm install -g @quad4/linking-tool
linking-tool
./bin/linking-tool --port 8080
```
### Docker
3. Open your browser at `http://localhost:8080`
### Using Docker
```sh
docker run -p 8080:8080 git.quad4.io/quad4-software/linking-tool
```
## Desktop Application
Then open your browser at `http://localhost:8080`
You can build the desktop application for your platform using Wails:
## Features
- Interactive graph visualization
- Multiple entity types (person, email, phone, address, domain, org, IP, social)
- Auto-save to IndexedDB
- Import/Export JSON
- Share link via base64 for smaller graphs
- Undo/Redo support
- PWA support (installable, offline-capable)
- Native desktop app support (via Wails)
- Single-binary lightweight web server
- Support for 32-bit and 64-bit architectures (runs on old Raspberry Pi Zero W)
## Installation Options
### Self-Hosted Web Server
The easiest way to self-host is using the single binary:
```sh
make desktop-build
task build
./bin/linking-tool --port 8080
```
The binary will be located in `bin/`.
The binary will be located in `bin/` after building.
### Desktop Application
Build the desktop application for your platform:
```sh
task desktop-build
```
The binary will be located in `bin/` after building.
## Development
### Prerequisites
- Go `1.25.5`
- Node.js
- pnpm
- Wails (for desktop app development)
### Setup
```sh
git clone https://git.quad4.io/quad4-software/linking-tool.git
cd linking-tool
pnpm install
```
### Makefile
### Task
The project uses a Makefile for all common tasks:
The project uses [Task](https://taskfile.dev/) for all development tasks.
```sh
make dev # Run development servers (Go & SvelteKit)
make build # Build the single binary web server
make help # List all available targets
```
| Task | Description |
|---------------------|-------------------------------------------|
| default | Show available tasks |
| dev | Run development servers (Go & SvelteKit) |
| build | Build the single binary web server |
| build:frontend | Build frontend only |
| build:backend | Build backend binary only |
| package | Package the application |
| release | Build binaries for all platforms |
| build-linux-amd64 | Build Linux AMD64 binary |
| build-linux-arm64 | Build Linux ARM64 binary |
| build-linux-armv6 | Build Linux ARMv6 binary |
| build-linux-armv7 | Build Linux ARMv7 binary |
| build-windows-amd64 | Build Windows AMD64 binary |
| build-darwin-amd64 | Build Darwin AMD64 binary |
| build-darwin-arm64 | Build Darwin ARM64 binary |
| build-freebsd-amd64 | Build FreeBSD AMD64 binary |
| docker-build | Build Docker image |
| docker-run | Run Docker container |
| docker-builder | Build and extract binaries using Docker |
| podman-build | Build Podman image |
| podman-run | Run Podman container |
| podman | Build and run Podman container |
| desktop-build | Build desktop application |
| desktop-linux | Build desktop application for Linux |
| desktop-windows | Build desktop application for Windows |
| desktop-darwin | Build desktop application for Darwin |
| desktop-dev | Run desktop app in development mode |
| clean | Clean build artifacts |
| setup | Setup development environment |
| install | Install dependencies |
| install:ci | Install dependencies for CI (frozen lock) |
| preview | Preview production build |
| check | Run type checking |
| lint | Run linter |
| format | Format code |
| version:minor | Bump minor version in package.json |
| version:major | Bump major version in package.json |
### Docker Build & Artifact Extraction
If you don't have the development environment (Go, Node, Wails) installed locally, you can build and extract binaries using Docker:
```sh
make docker-builder
example: task dev
you might to set alias alias task=`go-task`
```
This will build the server and desktop application inside a container and copy the resulting binaries to the `bin/` directory on your host machine.
## Contributing
Send us an email at [team@quad4.io](mailto:team@quad4.io) for any issues or feedback.
Send us an email at [team@quad4.io](mailto:team@quad4.io) for any issues or feedback.
## LICENSE
## License
[MIT](LICENSE)
[BSD 3-Clause](LICENSE)

17
SECURITY.md Normal file
View File

@@ -0,0 +1,17 @@
# Security Policy
If you have discovered a security vulnerability, please refer to [our website](https://quad4.io/security) for the latest security reporting procedures and guidelines.
## Vulnerability Management
- We use PNPM and [OSV](https://osv.dev/) to scan for package vulnerabilities in our dependencies.
## SAST
- Gosec for Go code.
- ESLint with eslint-plugin-security for JavaScript code.
## Dependency and Supply Chain
- All GitHub Actions used are forked and hosted on our Gitea instance, view them here https://git.quad4.io/actions.
- Actions are referenced using full URLs and cryptographically pinned to specific commit hashes for enhanced supply chain security.

222
Taskfile.yml Normal file
View File

@@ -0,0 +1,222 @@
version: '3'
vars:
BINARY_NAME: linking-tool
BUILD_DIR: bin
tasks:
default:
desc: Show available tasks
cmds:
- task --list
dev:
desc: Run development servers (Go & SvelteKit)
cmds:
- pnpm install
- pnpm run dev
build:frontend:
desc: Build frontend only
cmds:
- pnpm run build
build:backend:
desc: Build backend binary only
cmds:
- mkdir -p {{.BUILD_DIR}}
- CGO_ENABLED=0 go build -ldflags="-s -w" -o {{.BUILD_DIR}}/{{.BINARY_NAME}} main.go
build:
desc: Build the single binary web server
cmds:
- pnpm install
- pnpm run build
- mkdir -p {{.BUILD_DIR}}
- CGO_ENABLED=0 go build -ldflags="-s -w" -o {{.BUILD_DIR}}/{{.BINARY_NAME}} main.go
package:
desc: Package the application
deps: [build]
release:
desc: Build binaries for all platforms
deps: [build]
cmds:
- task: build-linux-amd64
- task: build-linux-arm64
- task: build-linux-armv6
- task: build-linux-armv7
- task: build-windows-amd64
- task: build-darwin-amd64
- task: build-darwin-arm64
- task: build-freebsd-amd64
build-linux-amd64:
desc: Build Linux AMD64 binary
cmds:
- GOOS=linux GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-amd64 main.go
build-linux-arm64:
desc: Build Linux ARM64 binary
cmds:
- GOOS=linux GOARCH=arm64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-arm64 main.go
build-linux-armv6:
desc: Build Linux ARMv6 binary
cmds:
- GOOS=linux GOARCH=arm GOARM=6 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-armv6 main.go
build-linux-armv7:
desc: Build Linux ARMv7 binary
cmds:
- GOOS=linux GOARCH=arm GOARM=7 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-armv7 main.go
build-windows-amd64:
desc: Build Windows AMD64 binary
cmds:
- GOOS=windows GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-windows-amd64.exe main.go
build-darwin-amd64:
desc: Build Darwin AMD64 binary
cmds:
- GOOS=darwin GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-amd64 main.go
build-darwin-arm64:
desc: Build Darwin ARM64 binary
cmds:
- GOOS=darwin GOARCH=arm64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-arm64 main.go
build-freebsd-amd64:
desc: Build FreeBSD AMD64 binary
cmds:
- GOOS=freebsd GOARCH=amd64 go build -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-freebsd-amd64 main.go
docker-build:
desc: Build Docker image
cmds:
- docker build -f docker/Dockerfile -t {{.BINARY_NAME}} .
docker-run:
desc: Run Docker container
cmds:
- docker run -p 8080:8080 {{.BINARY_NAME}}
docker-builder:
desc: Build and extract binaries using Docker
cmds:
- docker build -f docker/Dockerfile.build -t {{.BINARY_NAME}}-build .
- docker create --name {{.BINARY_NAME}}-temp {{.BINARY_NAME}}-build
- mkdir -p {{.BUILD_DIR}}
- docker cp {{.BINARY_NAME}}-temp:/bin/. {{.BUILD_DIR}}/
- docker cp {{.BINARY_NAME}}-temp:/desktop-bin/. {{.BUILD_DIR}}/
- docker rm {{.BINARY_NAME}}-temp
podman-build:
desc: Build Podman image
cmds:
- podman build -f docker/Dockerfile -t surveilled .
podman-run:
desc: Run Podman container
cmds:
- podman run --rm -p 3000:3000 surveilled
podman:
desc: Build and run Podman container
deps: [podman-build, podman-run]
desktop-build:
desc: Build desktop application
deps: [build]
cmds:
- mkdir -p desktop/frontend_dist
- rm -rf desktop/frontend_dist/*
- cp -r build/* desktop/frontend_dist/
- cd desktop && wails build -s
desktop-linux:
desc: Build desktop application for Linux
deps: [build]
cmds:
- mkdir -p desktop/frontend_dist
- rm -rf desktop/frontend_dist/*
- cp -r build/* desktop/frontend_dist/
- cd desktop && wails build -s -platform linux/amd64
desktop-windows:
desc: Build desktop application for Windows
deps: [build]
cmds:
- mkdir -p desktop/frontend_dist
- rm -rf desktop/frontend_dist/*
- cp -r build/* desktop/frontend_dist/
- cd desktop && wails build -s -platform windows/amd64
desktop-darwin:
desc: Build desktop application for Darwin
deps: [build]
cmds:
- mkdir -p desktop/frontend_dist
- rm -rf desktop/frontend_dist/*
- cp -r build/* desktop/frontend_dist/
- cd desktop && wails build -s -platform darwin/universal
desktop-dev:
desc: Run desktop application in development mode
deps: [build]
cmds:
- mkdir -p desktop/frontend_dist
- rm -rf desktop/frontend_dist/*
- cp -r build/* desktop/frontend_dist/
- cd desktop && wails dev
clean:
desc: Clean build artifacts
cmds:
- rm -rf .svelte-kit build node_modules node_modules/.vite dist package linking-tool tmp {{.BUILD_DIR}}
setup:
desc: Setup development environment
cmds:
- corepack enable
install:
desc: Install dependencies
cmds:
- pnpm install
install:ci:
desc: Install dependencies for CI (frozen lockfile)
cmds:
- pnpm install --frozen-lockfile
preview:
desc: Preview production build
cmds:
- pnpm run preview
check:
desc: Run type checking
cmds:
- pnpm run check
lint:
desc: Run linter
cmds:
- pnpm run lint
format:
desc: Format code
cmds:
- pnpm run format
version:minor:
desc: Bump minor version in package.json
cmds:
- pnpm version minor --no-git-tag-version
version:major:
desc: Bump major version in package.json
cmds:
- pnpm version major --no-git-tag-version

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env node
process.env.HOST = process.env.HOST || '127.0.0.1';
process.env.PORT = process.env.PORT || '3000';
import '../build/index.js';

View File

@@ -6,6 +6,7 @@ import (
"net"
"net/http"
"os"
"path/filepath"
"time"
"github.com/wailsapp/wails/v2/pkg/runtime"
@@ -128,7 +129,7 @@ func (a *App) SaveFile(filename string, content string) error {
return nil // Cancelled
}
return os.WriteFile(filePath, []byte(content), 0644)
return os.WriteFile(filePath, []byte(content), 0600)
}
// LoadFile shows an open dialog and returns the content of the selected file
@@ -150,10 +151,15 @@ func (a *App) LoadFile() (string, error) {
return "", nil // Cancelled
}
content, err := os.ReadFile(filePath)
absPath, err := filepath.Abs(filePath)
if err != nil {
return "", fmt.Errorf("invalid file path: %w", err)
}
cleanPath := filepath.Clean(absPath)
content, err := os.ReadFile(cleanPath)
if err != nil {
return "", err
}
return string(content), nil
}

View File

@@ -50,4 +50,3 @@ func main() {
println("Error:", err.Error())
}
}

View File

@@ -1,15 +1,14 @@
{
"name": "Linking Tool",
"assetdir": "frontend_dist",
"frontend:dir": "..",
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "http://localhost:5173",
"outputfilename": "linking-tool",
"author": {
"name": "Quad4",
"email": "dev@quad4.io"
}
"name": "Linking Tool",
"assetdir": "frontend_dist",
"frontend:dir": "..",
"frontend:install": "pnpm install",
"frontend:build": "pnpm run build",
"frontend:dev:watcher": "pnpm run dev",
"frontend:dev:serverUrl": "http://localhost:5173",
"outputfilename": "linking-tool",
"author": {
"name": "Quad4",
"email": "dev@quad4.io"
}
}

View File

@@ -1,10 +1,13 @@
# Stage 1: Build the frontend
FROM cgr.dev/chainguard/node:latest-dev AS node-builder
WORKDIR /app
COPY --chown=node:node package.json package-lock.json ./
RUN npm ci
USER root
RUN corepack enable && corepack prepare pnpm@10.25.0 --activate
USER node
COPY --chown=node:node package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY --chown=node:node . .
RUN npm run build
RUN pnpm run build
# Stage 2: Build the Go binary with embedded assets
FROM cgr.dev/chainguard/go:latest-dev AS go-builder
@@ -23,8 +26,10 @@ RUN apk add --no-cache ca-certificates
EXPOSE 8080
ENV PORT=8080
ENV HOST=0.0.0.0
ENV NODE_ENV=production
USER 65532
CMD ["./linking-tool"]

View File

@@ -1,6 +1,7 @@
import js from '@eslint/js';
import tsPlugin from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import securityPlugin from 'eslint-plugin-security';
import sveltePlugin from 'eslint-plugin-svelte';
import svelteParser from 'svelte-eslint-parser';
@@ -19,6 +20,8 @@ export default [
caches: 'readonly',
URL: 'readonly',
console: 'readonly',
Element: 'readonly',
EventListener: 'readonly',
HTMLElement: 'readonly',
HTMLImageElement: 'readonly',
HTMLInputElement: 'readonly',
@@ -65,10 +68,12 @@ export default [
},
plugins: {
'@typescript-eslint': tsPlugin,
security: securityPlugin,
svelte: sveltePlugin,
},
rules: {
...tsPlugin.configs.recommended.rules,
...securityPlugin.configs.recommended.rules,
},
},
{
@@ -109,6 +114,14 @@ export default [
},
},
{
ignores: ['node_modules/**', '.svelte-kit/**', 'build/**', 'dist/**', 'archive/**', 'desktop/frontend_dist/**', 'wailsjs/**'],
ignores: [
'node_modules/**',
'.svelte-kit/**',
'build/**',
'dist/**',
'archive/**',
'desktop/frontend_dist/**',
'wailsjs/**',
],
},
];

61
flake.lock generated Normal file
View File

@@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1766902085,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

94
flake.nix Normal file
View File

@@ -0,0 +1,94 @@
{
description = "Quad4 Linking Tool development environment";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
};
go = pkgs.go_1_25;
task = pkgs.buildGoModule rec {
pname = "task";
version = "3.46.3";
src = pkgs.fetchFromGitHub {
owner = "go-task";
repo = "task";
rev = "v${version}";
hash = "sha256-1bS8ZZAcemgRG7PTeGTFfd49T9u6U6CxxrbotwCM15A=";
};
vendorHash = "sha256-Tm0tqureCRwcP5KKDTa9TO1yZ3Px3ulf9/jKQDDTjDw=";
subPackages = [ "cmd/task" ];
doCheck = false;
meta = with pkgs.lib; {
description = "A task runner / simpler Make alternative written in Go";
homepage = "https://taskfile.dev/";
license = licenses.mit;
maintainers = with maintainers; [ ];
};
};
wailsSrc = pkgs.fetchFromGitHub {
owner = "wailsapp";
repo = "wails";
rev = "v2.11.0";
hash = "sha256-H1Nml2vhCx4IB/CT+kDro5joAw8ewpxoQjDgvqamAr8=";
};
wails = pkgs.buildGoModule rec {
pname = "wails";
version = "2.11.0";
src = pkgs.runCommand "${pname}-${version}-src" {} ''
cp -r ${wailsSrc}/v2 $out
chmod -R +w $out
'';
vendorHash = "sha256-HAIKhMKRTNI4hsm8Hvn5pUhnCTcitRxiw+WkVmxpfiU=";
subPackages = [ "cmd/wails" ];
doCheck = false;
meta = with pkgs.lib; {
description = "Build applications using Go + HTML + CSS + JS";
homepage = "https://wails.io/";
license = licenses.mit;
maintainers = with maintainers; [ ];
};
};
in
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
go
task
nodejs_20
nodePackages.pnpm
wails
gcc
pkg-config
];
shellHook = ''
echo "Quad4 Linking Tool Development Environment"
echo "Go version: $(go version)"
echo "Task version: $(task --version 2>/dev/null || echo 'installed')"
echo "Node version: $(node --version)"
echo "pnpm version: $(pnpm --version)"
echo "Wails version: $(wails version 2>/dev/null || echo 'installed')"
'';
};
});
}

2
go.mod
View File

@@ -1,6 +1,6 @@
module git.quad4.io/Quad4-Software/linking-tool
go 1.24
go 1.25.5
require github.com/wailsapp/wails/v2 v2.11.0

11
main.go
View File

@@ -64,7 +64,7 @@ func corsMiddleware(allowedOrigins []string) func(http.HandlerFunc) http.Handler
func main() {
frontendPath := flag.String("frontend", "", "Path to custom frontend build directory (overrides embedded assets)")
host := flag.String("host", "0.0.0.0", "Host to bind the server to")
host := flag.String("host", "127.0.0.1", "Host to bind the server to")
port := flag.String("port", "", "Port to listen on (overrides PORT env var)")
allowedOriginsStr := flag.String("allowed-origins", os.Getenv("ALLOWED_ORIGINS"), "Comma-separated list of allowed CORS origins")
@@ -78,6 +78,10 @@ func main() {
}
}
if hostEnv := os.Getenv("HOST"); hostEnv != "" {
*host = hostEnv
}
if *port == "" {
*port = os.Getenv("PORT")
if *port == "" {
@@ -90,7 +94,9 @@ func main() {
http.HandleFunc("/api/ping", cors(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"ok"}`))
if _, err := w.Write([]byte(`{"status":"ok"}`)); err != nil {
log.Printf("Error writing response: %v", err)
}
}))
// Static Assets
@@ -138,4 +144,3 @@ func main() {
log.Fatal(err)
}
}

4131
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,8 @@
{
"name": "@quad4/linking-tool",
"version": "1.4.0",
"version": "1.5.1",
"license": "BSD-3-Clause",
"author": "Quad4",
"type": "module",
"main": "./build/index.js",
"bin": {
@@ -9,9 +11,15 @@
"engines": {
"node": ">=18.0.0"
},
"packageManager": "pnpm@10.25.0",
"publishConfig": {
"registry": "https://git.quad4.io/api/packages/quad4-software/npm/"
},
"pnpm": {
"overrides": {
"cookie": "1.1.1"
}
},
"files": [
"build/**/*",
"bin/**/*",
@@ -27,26 +35,27 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "eslint .",
"package": "svelte-kit sync && vite build",
"desktop:dev": "make desktop-dev",
"desktop:build": "make desktop-build"
"package": "svelte-kit sync && VITE_APP_VERSION=$(node -p \"require('./package.json').version\") vite build",
"desktop:dev": "task desktop-dev",
"desktop:build": "task desktop-build"
},
"devDependencies": {
"@eslint/js": "^9.39.2",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.49.1",
"@sveltejs/kit": "^2.49.2",
"@sveltejs/vite-plugin-svelte": "^6.2.1",
"@typescript-eslint/eslint-plugin": "^8.50.1",
"@typescript-eslint/parser": "^8.50.1",
"@typescript-eslint/eslint-plugin": "^8.51.0",
"@typescript-eslint/parser": "^8.51.0",
"eslint": "^9.39.2",
"eslint-plugin-security": "^3.0.1",
"eslint-plugin-svelte": "^3.13.1",
"prettier": "^3.7.4",
"prettier-plugin-svelte": "^3.4.1",
"svelte": "^5.45.6",
"svelte-check": "^4.3.4",
"svelte": "^5.46.1",
"svelte-check": "^4.3.5",
"svelte-eslint-parser": "^1.4.1",
"typescript": "^5.9.3",
"vite": "^7.2.6"
"vite": "^7.3.0"
},
"dependencies": {
"autoprefixer": "^10.4.23",

View File

@@ -1 +0,0 @@
6da4cdcafa6966a9d35d5e1ce48583eb

2549
pnpm-lock.yaml generated Normal file
View File

File diff suppressed because it is too large Load Diff

3
renovate.json Normal file
View File

@@ -0,0 +1,3 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

8856
sbom/sbom.cyclonedx.json Normal file
View File

File diff suppressed because it is too large Load Diff

12578
sbom/sbom.spdx.json Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,5 +2,5 @@
set -euo pipefail
echo "Building app..."
VITE_APP_VERSION=$(node -p "require('./package.json').version") npm run build
VITE_APP_VERSION=$(node -p "require('./package.json').version") pnpm run build

View File

@@ -21,4 +21,3 @@ swContent = swContent.replace(
writeFileSync(swPath, swContent);
console.log(`Injected version ${version} into service worker`);

View File

@@ -23,20 +23,16 @@ VULNS=$(jq -r '
.results[]? |
.source as $src |
.vulns[]? |
select(
(.database_specific.severity // "" | ascii_upcase | test("HIGH|CRITICAL")) or
(.severity[]?.score // "" | tostring | split("/")[0] | tonumber? // 0 | . >= 7.0)
) |
"\(.id) (source: \($src))"
' "$OSV_JSON")
if [ -n "$VULNS" ]; then
echo "OSV scan found HIGH/CRITICAL vulnerabilities:"
echo "OSV scan found vulnerabilities:"
echo "$VULNS" | while IFS= read -r line; do
echo " - $line"
done
exit 1
else
echo "OSV scan: no HIGH/CRITICAL vulnerabilities found."
echo "OSV scan: no vulnerabilities found."
fi

View File

File diff suppressed because it is too large Load Diff

80
src/lib/constants.ts Normal file
View File

@@ -0,0 +1,80 @@
import { User, Mail, Phone, MapPin, Globe, Building2, Network, AtSign } from 'lucide-svelte';
export const DB_NAME = 'quad4-linking-db';
export const DB_VERSION = 2;
export const STORE_NAME = 'graphs';
export const SETTINGS_STORE = 'settings';
export const UNDO_STORE = 'undo_stack';
export const REDO_STORE = 'redo_stack';
export const MAX_HISTORY = 100;
export const ALLOWED_IMAGE_TYPES = ['image/png', 'image/jpeg', 'image/webp'];
export const MAX_IMAGE_BYTES = 2 * 1024 * 1024;
export type RelationshipType =
| 'Linked'
| 'Works For'
| 'Knows'
| 'Owns'
| 'Associated With'
| 'Related To'
| 'Connected To';
export type RelationshipStrength = 'weak' | 'medium' | 'strong';
export const RELATIONSHIP_COLORS: Record<RelationshipType, string> = {
Linked: '#525252',
'Works For': '#3b82f6',
Knows: '#10b981',
Owns: '#f59e0b',
'Associated With': '#8b5cf6',
'Related To': '#ec4899',
'Connected To': '#06b6d4',
};
export const relationshipTypes: RelationshipType[] = [
'Linked',
'Works For',
'Knows',
'Owns',
'Associated With',
'Related To',
'Connected To',
];
export const relationshipStrengths: RelationshipStrength[] = ['weak', 'medium', 'strong'];
export type NodeType =
| 'person'
| 'email'
| 'phone'
| 'address'
| 'domain'
| 'org'
| 'ip'
| 'social';
export const iconMap: Record<NodeType, typeof User> = {
person: User,
email: Mail,
phone: Phone,
address: MapPin,
domain: Globe,
org: Building2,
ip: Network,
social: AtSign,
};
export const nodeTypes = Object.keys(iconMap) as NodeType[];
export const typeColors: Record<NodeType, string> = {
person: '#ef4444',
email: '#f97316',
phone: '#eab308',
address: '#10b981',
domain: '#f43f5e',
org: '#be123c',
ip: '#71717a',
social: '#db2777',
};

View File

@@ -1,36 +0,0 @@
import { User, Mail, Phone, MapPin, Globe, Building2, Network, AtSign } from 'lucide-svelte';
import type { ComponentType } from 'svelte';
export type NodeType =
| 'person'
| 'email'
| 'phone'
| 'address'
| 'domain'
| 'org'
| 'ip'
| 'social';
export const iconMap: Record<NodeType, ComponentType> = {
person: User,
email: Mail,
phone: Phone,
address: MapPin,
domain: Globe,
org: Building2,
ip: Network,
social: AtSign,
};
export const nodeTypes = Object.keys(iconMap) as NodeType[];
export const typeColors: Record<NodeType, string> = {
person: '#ef4444',
email: '#f97316',
phone: '#eab308',
address: '#10b981',
domain: '#f43f5e',
org: '#be123c',
ip: '#71717a',
social: '#db2777',
};

View File

@@ -1,14 +1,15 @@
<script lang="ts">
import '../app.css';
import { onMount } from 'svelte';
import type { Snippet } from 'svelte';
let showUpdateAvailable = false;
let { children }: { children: Snippet } = $props();
let showUpdateAvailable = $state(false);
let registration: ServiceWorkerRegistration | null = null;
function checkForUpdates() {
if (registration && navigator.onLine) {
registration.update().catch(() => {
});
registration.update().catch(() => {});
}
}
@@ -76,13 +77,13 @@
<p class="text-xs text-neutral-400 mt-1">A new version is available. Reload to update.</p>
</div>
<button
on:click={reloadApp}
onclick={reloadApp}
class="px-4 py-2 bg-accent-red text-white rounded-md text-sm font-medium hover:bg-accent-red-dark transition-colors"
>
Reload
</button>
<button
on:click={() => (showUpdateAvailable = false)}
onclick={() => (showUpdateAvailable = false)}
class="text-neutral-400 hover:text-white transition-colors"
aria-label="Dismiss"
>
@@ -105,4 +106,4 @@
</div>
{/if}
<slot />
{@render children()}

View File

@@ -1,4 +1,4 @@
const CACHE_VERSION = '1.4.0';
const CACHE_VERSION = '1.5.1';
const CACHE_NAME = `quad4-linking-tool-${CACHE_VERSION}`;
const urlsToCache = ['/', '/favicon.svg', '/manifest.json'];

View File

@@ -1,11 +0,0 @@
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter(),
},
};
export default config;

View File

@@ -4,6 +4,16 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
compilerOptions: (id) => {
if (id && id.includes('node_modules')) {
return {
runes: false, // Disable runes for external dependencies that might not support it yet (lucide-svelte)
};
}
return {
runes: true,
};
},
kit: {
adapter: adapter({
@@ -11,9 +21,9 @@ const config = {
assets: 'build',
fallback: 'index.html',
precompress: false,
strict: true
})
}
strict: true,
}),
},
};
export default config;