From c649eaf343291b3b8263ebf11e5f2bb5c4807953 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:21:47 -0400 Subject: [PATCH 01/13] fix(proxy): remove double slash in nginx API proxy_pass API_URL already includes a trailing slash, so the extra slash in proxy_pass produced //auth/login paths, causing 404s. Also clear ROOT_PATH since nginx strips /api/ before proxying. --- docker-compose.yml | 2 +- frontend/nginx.conf.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 14842b2..cff35c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,7 +40,7 @@ services: JWT_SECRET: ${JWT_SECRET:-sparc-secret-key-change-in-production} CORS_ORIGINS: ${CORS_ORIGINS:-} APP_ENV: ${APP_ENV:-development} - ROOT_PATH: /api + ROOT_PATH: "" ports: - "8000:8000" depends_on: diff --git a/frontend/nginx.conf.template b/frontend/nginx.conf.template index c24b137..b36c4df 100644 --- a/frontend/nginx.conf.template +++ b/frontend/nginx.conf.template @@ -15,7 +15,7 @@ server { # Proxy API requests to backend location /api/ { - proxy_pass ${API_URL}/; + proxy_pass ${API_URL}; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; From 9745ed75a8944695ec4e829a78e743ea6b0ae69e Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:27:56 -0400 Subject: [PATCH 02/13] feat(docker): add registry images to compose services Add gitea.leeworks.dev image references alongside build directives so `docker compose up` pulls pre-built images while `--build` still builds from local sources. --- docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index cff35c7..ce7d077 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,7 @@ services: restart: unless-stopped init-db: + image: gitea.leeworks.dev/0xwheatyz/sparc:latest build: . container_name: sparc-init-db command: python scripts/init_database.py @@ -29,6 +30,7 @@ services: restart: "no" api: + image: gitea.leeworks.dev/0xwheatyz/sparc:latest build: . container_name: sparc-api command: uvicorn SPARC.api:app --host 0.0.0.0 --port 8000 @@ -76,6 +78,7 @@ services: - s3 dashboard: + image: gitea.leeworks.dev/0xwheatyz/sparc:frontend-latest build: ./frontend container_name: sparc-dashboard ports: From 2ae6280566c0bace11cdee020833826b857ccaa9 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:45:41 -0400 Subject: [PATCH 03/13] ci: fix test to use apt instead of apk --- .gitea/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 71173d3..524314b 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -16,7 +16,7 @@ jobs: - name: Install system dependencies shell: sh run: | - apk add --no-cache git python3 py3-pip gcc musl-dev libpq-dev python3-dev + apt upgrade && apt install git python3 py3-pip gcc musl-dev libpq-dev python3-dev - name: Checkout code shell: sh From c6760a39a17bd91331c998742145352fd5291e57 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:47:46 -0400 Subject: [PATCH 04/13] ci(test): use apt-get with correct Ubuntu packages in workflow Replace Alpine-style commands (apk, py3-pip, musl-dev) and incorrect apt usage with proper apt-get invocations and Debian package names for the ubuntu-latest runner. --- .gitea/workflows/test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 524314b..c9b16d6 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -16,7 +16,7 @@ jobs: - name: Install system dependencies shell: sh run: | - apt upgrade && apt install git python3 py3-pip gcc musl-dev libpq-dev python3-dev + apt-get update && apt-get install -y git python3 python3-pip gcc libpq-dev python3-dev - name: Checkout code shell: sh @@ -37,7 +37,7 @@ jobs: - name: Install Node.js and frontend dependencies shell: sh run: | - apk add --no-cache nodejs npm + apt-get install -y nodejs npm cd frontend && npm ci - name: Verify generated API types are up to date From c17a0d006a37218f7bb00933b3ac8a42c3c21b02 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:49:15 -0400 Subject: [PATCH 05/13] ci: fix pip install --- .gitea/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index c9b16d6..69b7c92 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -27,7 +27,7 @@ jobs: - name: Install Python dependencies shell: sh run: | - pip3 install --break-system-packages -r requirements.txt ruff + pip3 install -r requirements.txt ruff - name: Run ruff linter shell: sh From 02e1c4112669cf586608ee0696de98a470dbaf82 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:57:17 -0400 Subject: [PATCH 06/13] ci(linters): removed ruff requirement, as causing working builds to fail --- .gitea/workflows/build.yaml | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index beb2354..7752c55 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -15,7 +15,7 @@ jobs: - name: Install system dependencies shell: sh run: | - apk add --no-cache git python3 py3-pip gcc musl-dev libpq-dev python3-dev + apt update && apt install git python3 py3-pip gcc musl-dev libpq-dev python3-dev - name: Checkout code shell: sh @@ -26,17 +26,17 @@ jobs: - name: Install Python dependencies shell: sh run: | - pip3 install --break-system-packages -r requirements.txt ruff + pip3 install -r requirements.txt ruff - - name: Run ruff linter - shell: sh - run: | - ruff check SPARC/ tests/ +# - name: Run ruff linter +# shell: sh +# run: | +# ruff check SPARC/ tests/ - name: Install Node.js and check TypeScript types shell: sh run: | - apk add --no-cache nodejs npm + apt install nodejs npm cd frontend npm ci npm run generate:local @@ -47,16 +47,16 @@ jobs: fi npx tsc --noEmit - - name: Run pytest - shell: sh - env: - DATABASE_URL: "sqlite://" - API_KEY: "test-key" - OPENROUTER_API_KEY: "test-key" - JWT_SECRET: "test-secret-for-ci" - APP_ENV: "development" - run: | - python3 -m pytest tests/ -v --tb=short -x +# - name: Run pytest +# shell: sh +# env: +# DATABASE_URL: "sqlite://" +# API_KEY: "test-key" +# OPENROUTER_API_KEY: "test-key" +# JWT_SECRET: "test-secret-for-ci" +# APP_ENV: "development" +# run: | +# python3 -m pytest tests/ -v --tb=short -x build-api: needs: test @@ -65,7 +65,7 @@ jobs: - name: Install dependencies shell: sh run: | - apk add --no-cache git docker-cli + apt install git docker-cli - name: Checkout code shell: sh @@ -137,7 +137,7 @@ jobs: - name: Install dependencies shell: sh run: | - apk add --no-cache git docker-cli + apt install git docker-cli - name: Checkout code shell: sh From 89fec43aa27633c5c75dbe345ebe1a600615f78a Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 20:59:11 -0400 Subject: [PATCH 07/13] ci(build): use apt-get with correct Ubuntu package names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace apt with apt-get, add -y flag, fix Alpine-style package names (py3-pip → python3-pip, docker-cli → docker.io), and drop musl-dev. --- .gitea/workflows/build.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 7752c55..ecd15cf 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -15,7 +15,7 @@ jobs: - name: Install system dependencies shell: sh run: | - apt update && apt install git python3 py3-pip gcc musl-dev libpq-dev python3-dev + apt-get update && apt-get install -y git python3 python3-pip gcc libpq-dev python3-dev - name: Checkout code shell: sh @@ -36,7 +36,7 @@ jobs: - name: Install Node.js and check TypeScript types shell: sh run: | - apt install nodejs npm + apt-get install -y nodejs npm cd frontend npm ci npm run generate:local @@ -65,7 +65,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt install git docker-cli + apt-get install -y git docker.io - name: Checkout code shell: sh @@ -137,7 +137,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt install git docker-cli + apt-get install -y git docker.io - name: Checkout code shell: sh From bd10925c97901df0f645527768ecc644058a74fb Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 21:06:34 -0400 Subject: [PATCH 08/13] chore: updated package-lock.json --- frontend/package-lock.json | 257 +++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ca0ca36..c7309fc 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -26,6 +26,7 @@ "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-refresh": "^0.4.7", "globals": "^15.8.0", + "openapi-typescript": "^7.0.0", "postcss": "^8.4.39", "tailwindcss": "^3.4.4", "typescript": "~5.5.3", @@ -1025,6 +1026,82 @@ "node": ">= 8" } }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/ajv/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/config": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.0.tgz", + "integrity": "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.34.11", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.11.tgz", + "integrity": "sha512-V09ayfnb5GyysmvARbt+voFZAjGcf7hSYxOYxSkCc4fbH/DTfq5YWoec8cflvmHHqyIFbqvmGKmYFzqhr9zxDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "8.11.2", + "@redocly/config": "0.22.0", + "colorette": "1.4.0", + "https-proxy-agent": "7.0.6", + "js-levenshtein": "1.1.6", + "js-yaml": "4.1.1", + "minimatch": "5.1.9", + "pluralize": "8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=18.17.0", + "npm": ">=9.5.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@remix-run/router": { "version": "1.23.2", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", @@ -1906,6 +1983,16 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", @@ -1923,6 +2010,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2190,6 +2287,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2257,6 +2361,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3165,6 +3276,20 @@ "node": ">= 0.4" } }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3202,6 +3327,19 @@ "node": ">=0.8.19" } }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/internmap": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", @@ -3290,6 +3428,16 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3608,6 +3756,40 @@ "node": ">= 6" } }, + "node_modules/openapi-typescript": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.13.0.tgz", + "integrity": "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.34.6", + "ansi-colors": "^4.1.3", + "change-case": "^5.4.4", + "parse-json": "^8.3.0", + "supports-color": "^10.2.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.x" + } + }, + "node_modules/openapi-typescript/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3671,6 +3853,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3738,6 +3938,16 @@ "node": ">= 6" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.5.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", @@ -4124,6 +4334,16 @@ "decimal.js-light": "^2.4.1" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -4510,6 +4730,19 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.5.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", @@ -4589,6 +4822,13 @@ "punycode": "^2.1.0" } }, + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, + "license": "MIT" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4711,6 +4951,23 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", From 90e58949fc45443875719a45125b0ad6468ab970 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 21:11:09 -0400 Subject: [PATCH 09/13] ci: updated the docker install canidate --- .gitea/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index ecd15cf..529c2fb 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -65,7 +65,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get install -y git docker.io + apt-get install -y git docker-ce - name: Checkout code shell: sh @@ -137,7 +137,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get install -y git docker.io + apt-get install -y git docker-ce - name: Checkout code shell: sh From 88812b5967be13a84424aacc83c31c4520c78667 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 21:15:41 -0400 Subject: [PATCH 10/13] ci(build): updated the apt command --- .gitea/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 529c2fb..188f178 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -65,7 +65,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get install -y git docker-ce + apt-get update && apt-get install -y git docker-ce - name: Checkout code shell: sh @@ -137,7 +137,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get install -y git docker-ce + apt-get update && apt-get install -y git docker-ce - name: Checkout code shell: sh From ef97710d1c6c3056ce8a2162f03602d77705bd20 Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 21:21:22 -0400 Subject: [PATCH 11/13] ci(build): another docker install candiate --- .gitea/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 188f178..d3edcb1 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -65,7 +65,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get update && apt-get install -y git docker-ce + apt-get update && apt-get install -y git docker-ce docker-ce-cli containerd.io - name: Checkout code shell: sh @@ -137,7 +137,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get update && apt-get install -y git docker-ce + apt-get update && apt-get install -y git docker-ce docker-ce-cli containerd.io - name: Checkout code shell: sh From 68ee19025adc9ee2f4a4ca771f5ada6b6d524d5e Mon Sep 17 00:00:00 2001 From: 0xWheatyz Date: Thu, 2 Apr 2026 21:28:26 -0400 Subject: [PATCH 12/13] ci(build): use docker.io package instead of docker-ce in build jobs The Debian Bullseye runner image doesn't have the Docker CE repository configured. docker.io is available from default repos. --- .gitea/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index d3edcb1..80acc27 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -65,7 +65,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get update && apt-get install -y git docker-ce docker-ce-cli containerd.io + apt-get update && apt-get install -y git docker.io - name: Checkout code shell: sh @@ -137,7 +137,7 @@ jobs: - name: Install dependencies shell: sh run: | - apt-get update && apt-get install -y git docker-ce docker-ce-cli containerd.io + apt-get update && apt-get install -y git docker.io - name: Checkout code shell: sh From b32eebff8ad93fee00f6873cd7c5f1ff223d5386 Mon Sep 17 00:00:00 2001 From: agent-company Date: Sun, 19 Apr 2026 20:06:10 +0000 Subject: [PATCH 13/13] ci: enable ruff linting and pytest in CI pipeline Uncomment the ruff check and pytest steps in the Gitea Actions build workflow so that linting violations and test failures block image builds. Fix all pre-existing ruff violations (E402 import ordering in analyzer.py, F821 undefined name in api.py, I001 unsorted imports in test files, F401 unused import in test_rate_limit.py). Closes leeworks-agents/SPARC#1559 Closes leeworks-agents/SPARC#1560 Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitea/workflows/build.yaml | 29 +++++++++++++++-------------- SPARC/analyzer.py | 4 ++-- SPARC/api.py | 8 ++++++-- tests/test_auth.py | 1 + tests/test_rate_limit.py | 3 ++- tests/test_security.py | 7 +++++++ 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 80acc27..aeeb5c1 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -28,10 +28,10 @@ jobs: run: | pip3 install -r requirements.txt ruff -# - name: Run ruff linter -# shell: sh -# run: | -# ruff check SPARC/ tests/ + - name: Run ruff linter + shell: sh + run: | + ruff check SPARC/ tests/ - name: Install Node.js and check TypeScript types shell: sh @@ -47,16 +47,17 @@ jobs: fi npx tsc --noEmit -# - name: Run pytest -# shell: sh -# env: -# DATABASE_URL: "sqlite://" -# API_KEY: "test-key" -# OPENROUTER_API_KEY: "test-key" -# JWT_SECRET: "test-secret-for-ci" -# APP_ENV: "development" -# run: | -# python3 -m pytest tests/ -v --tb=short -x + - name: Run pytest + shell: sh + env: + DATABASE_URL: "sqlite://" + API_KEY: "test-key" + OPENROUTER_API_KEY: "test-key" + JWT_SECRET: "test-secret-for-ci" + APP_ENV: "development" + run: | + pip3 install pytest + python3 -m pytest tests/ -v --tb=short -x build-api: needs: test diff --git a/SPARC/analyzer.py b/SPARC/analyzer.py index 31ad7f1..1ebceaf 100644 --- a/SPARC/analyzer.py +++ b/SPARC/analyzer.py @@ -10,13 +10,13 @@ from concurrent.futures import ThreadPoolExecutor, as_completed from typing import Callable from SPARC import config - -logger = logging.getLogger(__name__) from SPARC.database import DatabaseClient from SPARC.llm import LLMAnalyzer from SPARC.serp_api import SERP from SPARC.types import BatchAnalysisResult, CompanyAnalysisResult, Patent, Patents +logger = logging.getLogger(__name__) + class CompanyAnalyzer: """Orchestrates end-to-end company performance analysis via patents.""" diff --git a/SPARC/api.py b/SPARC/api.py index 3a28033..a42ddd7 100644 --- a/SPARC/api.py +++ b/SPARC/api.py @@ -3,9 +3,14 @@ Provides REST API endpoints for analyzing company patent portfolios. """ +from __future__ import annotations + from contextlib import asynccontextmanager from datetime import datetime -from typing import Annotated, List +from typing import TYPE_CHECKING, Annotated, List + +if TYPE_CHECKING: + from SPARC.database import DatabaseClient from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException, Query, Request from fastapi.middleware.cors import CORSMiddleware @@ -653,7 +658,6 @@ async def export_company_pdf( PDF file download """ import io - import textwrap from reportlab.lib import colors from reportlab.lib.pagesizes import letter diff --git a/tests/test_auth.py b/tests/test_auth.py index de79259..bb4378a 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -175,6 +175,7 @@ class TestGetMe: from datetime import timedelta import jwt as pyjwt + from SPARC.auth import JWT_ALGORITHM, JWT_SECRET payload = { diff --git a/tests/test_rate_limit.py b/tests/test_rate_limit.py index f9f06af..8d0adf0 100644 --- a/tests/test_rate_limit.py +++ b/tests/test_rate_limit.py @@ -1,7 +1,8 @@ """Tests for rate limiting on auth endpoints.""" +from unittest.mock import MagicMock, patch + import pytest -from unittest.mock import Mock, patch, MagicMock from fastapi.testclient import TestClient from SPARC.api import app diff --git a/tests/test_security.py b/tests/test_security.py index b6e4be1..b34deec 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -14,6 +14,7 @@ class TestJWTSecretStartupCheck: with patch.dict(os.environ, {"APP_ENV": "production"}): # Reload config to pick up the new APP_ENV import importlib + import SPARC.config importlib.reload(SPARC.config) @@ -31,6 +32,7 @@ class TestJWTSecretStartupCheck: """Starting with default secret and APP_ENV=development must not raise.""" with patch.dict(os.environ, {"APP_ENV": "development"}): import importlib + import SPARC.config importlib.reload(SPARC.config) @@ -46,6 +48,7 @@ class TestJWTSecretStartupCheck: """Starting with a custom secret in production must not raise.""" with patch.dict(os.environ, {"APP_ENV": "production"}): import importlib + import SPARC.config importlib.reload(SPARC.config) @@ -65,6 +68,7 @@ class TestJWTSecretStartupCheck: env.pop("APP_ENV", None) with patch.dict(os.environ, env, clear=True): import importlib + import SPARC.config importlib.reload(SPARC.config) @@ -84,6 +88,7 @@ class TestCORSConfig: """When CORS_ORIGINS is unset, defaults to localhost origins.""" with patch.dict(os.environ, {"CORS_ORIGINS": ""}): import importlib + import SPARC.config importlib.reload(SPARC.config) assert SPARC.config.cors_origins == [ @@ -95,6 +100,7 @@ class TestCORSConfig: """Setting CORS_ORIGINS configures allowed origins.""" with patch.dict(os.environ, {"CORS_ORIGINS": "https://sparc.example.com,https://app.example.com"}): import importlib + import SPARC.config importlib.reload(SPARC.config) assert SPARC.config.cors_origins == [ @@ -109,6 +115,7 @@ class TestCORSConfig: """A single origin without comma works correctly.""" with patch.dict(os.environ, {"CORS_ORIGINS": "https://sparc.example.com"}): import importlib + import SPARC.config importlib.reload(SPARC.config) assert SPARC.config.cors_origins == ["https://sparc.example.com"]