Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f357fc8
Updated Dockerfiles
cyberphor Mar 7, 2026
b46fed5
Added a CI pipeline
cyberphor Mar 7, 2026
75eeeb1
Updated the CI pipeline
cyberphor Mar 7, 2026
7edddf1
Removed special char from CI pipeline
cyberphor Mar 7, 2026
9b0fe20
Added artifact name to SCA job
cyberphor Mar 7, 2026
279370a
Updated job names again
cyberphor Mar 7, 2026
c80b9be
Fixed a few QA findings
cyberphor Mar 7, 2026
5b1e363
Fixed a few more QA findings
cyberphor Mar 7, 2026
c7c6cc0
Fixed even more QA findings
cyberphor Mar 7, 2026
8029564
Updated CI pipeline again
cyberphor Mar 7, 2026
f24a53f
Fixed CI pipeline again
cyberphor Mar 7, 2026
6fe9cda
Extended CI pipeline
cyberphor Mar 7, 2026
50f28ba
Fixed CI pipeline for docs
cyberphor Mar 7, 2026
9ccf42a
Fixed CI pipeline for docs (again)
cyberphor Mar 7, 2026
404cd04
Fixed job name
cyberphor Mar 7, 2026
4ae7162
Spiced up the docs home page
cyberphor Mar 7, 2026
684d419
Removed mkdocs module
cyberphor Mar 7, 2026
333606d
Updated docs
cyberphor Mar 7, 2026
089e499
Updated CI pipeline logic
cyberphor Mar 7, 2026
01314e3
Updated docs
cyberphor Mar 7, 2026
ffb09bf
Updated the CI pipeline
cyberphor Mar 7, 2026
d0eb907
Updated all 3 components
cyberphor Mar 8, 2026
65d71d9
Updated container layout
cyberphor Mar 21, 2026
b8b39c2
Updated docs CI pipeline
cyberphor Mar 21, 2026
855188f
Updated docs CI pipeline
cyberphor Mar 21, 2026
a2c0857
Updated CI pipeline for agents
cyberphor Mar 21, 2026
031cb7e
Updated CI pipeline for agents
cyberphor Mar 21, 2026
e891aee
Updated CI pipeline for docs
cyberphor Mar 21, 2026
e2e78ab
Updated CI pipeline for docs
cyberphor Mar 21, 2026
25ec77c
Updated CI pipeline for docs
cyberphor Mar 21, 2026
32aa1fb
Updated CI pipeline for docs
cyberphor Mar 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions .env.local

This file was deleted.

42 changes: 42 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Docs

on:
push:
branches: [ "**" ]
paths:
- "docs/**"

jobs:
build:
name: Build docs
runs-on: ubuntu-latest
steps:
- name: Clone the repository
uses: actions/checkout@v4
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install dependencies
run: pip install mkdocs
- name: Build docs
run: mkdocs build -f docs/mkdocs.yml
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/site/
deploy:
name: Deploy docs
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deploy.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deploy
uses: actions/deploy-pages@v4
119 changes: 119 additions & 0 deletions .github/workflows/integrate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: Integrate

on:
push:
branches: [ "**" ]
paths:
- "emass/**"
- "tools/**"
- "agent/**"
- "frontend/**"
- "docs/**"

jobs:
secrets:
name: Secrets Check
runs-on: ubuntu-latest
steps:
- name: Clone the repository
uses: actions/checkout@v4
- name: Run Trufflehog
id: trufflehog
uses: trufflesecurity/trufflehog@main
continue-on-error: false

dockerfile:
name: Dockerfile Lint Check
needs: secrets
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
container:
- emass
- tools
- agent/openai_gpt-4o
- frontend
- docs
steps:
- uses: actions/checkout@v4
- uses: hadolint/hadolint-action@v3.1.0
with:
failure-threshold: error
dockerfile: ${{ matrix.container }}/Dockerfile

qa:
name: Quality Assurance Check
needs: secrets
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
container:
- emass
- tools
- agent/openai_gpt-4o
- frontend
- docs
steps:
- name: Clone the repository
uses: actions/checkout@v4
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Python dependencies
run: python -m pip install black
- name: Check code formatting
run: black --diff --color --check ${{ matrix.container }}

sca:
name: Software Composition Analysis
needs: secrets
runs-on: ubuntu-latest
permissions:
actions: read
contents: write
strategy:
fail-fast: false
matrix:
container:
- emass
- tools
- agent/openai_gpt-4o
- frontend
- docs
steps:
- uses: actions/checkout@v4
- name: Generate an SBOM
uses: anchore/sbom-action@v0
with:
path: ${{ matrix.container }}
output-file: sbom-${{ matrix.container }}.json
artifact-name: sbom-${{ matrix.container }}
- name: Check for CVEs
uses: anchore/scan-action@v3
with:
sbom: sbom-${{ matrix.container }}.json
severity-cutoff: high

sast:
name: Static App Security Test
needs: secrets
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
container:
- emass
- tools
- agent/openai_gpt-4o
- frontend
- docs
container:
image: semgrep/semgrep
steps:
- name: Clone the repository
uses: actions/checkout@v4
- name: Perform a SAST scan
run: semgrep scan --config auto ${{ matrix.container }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,6 @@ __marimo__/
*.gguf
client.crt
client.key

uv.lock
.env.secrets
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2025 Victor Fernandez III
Copyright (c) 2026 Victor Fernandez III

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
34 changes: 12 additions & 22 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,39 +1,29 @@
# ---------------------------------------------------------
# Set the default target.
# Misc.
# ---------------------------------------------------------

# Set the default goal.
.DEFAULT_GOAL := build

# ---------------------------------------------------------
# Load environment variables and secrets.
# ---------------------------------------------------------

.PHONY: print-dot-env-files-used
.SILENT: print-dot-env-files-used
# Tell Docker to build images in parallel.
COMPOSE_BAKE := true

# Load the specified environment variables file.
ENV_FILE ?= .env.local
# Set the environment variables file to ".env" if an argument is not provided.
ENV_FILE ?= .env
include $(ENV_FILE)

# Load the specified environment variables file.
SECRETS_FILE ?= .env.local.secrets
include $(SECRETS_FILE)

# Set the Docker Compose profile to "all" if an argument is not provided.
DOCKER_COMPOSE_PROFILE ?= all

print-dot-env-files-used:
@echo "[+] Set environment variables using $(ENV_FILE) and $(SECRETS_FILE)"

# ---------------------------------------------------------
# Build the containers.
# ---------------------------------------------------------

.PHONY: build
.SILENT: build

build: print-dot-env-files-used
docker compose --profile $(DOCKER_COMPOSE_PROFILE) --env-file $(ENV_FILE) --env-file $(SECRETS_FILE) build --no-cache
build:
docker compose --profile $(DOCKER_COMPOSE_PROFILE) --env-file $(ENV_FILE) build --no-cache

# ---------------------------------------------------------
# Start the containers.
Expand All @@ -42,8 +32,8 @@ build: print-dot-env-files-used
.PHONY: start
.SILENT: start

start: print-dot-env-files-used
docker compose --profile $(DOCKER_COMPOSE_PROFILE) --env-file $(ENV_FILE) --env-file $(SECRETS_FILE) up -d
start:
docker compose --profile $(DOCKER_COMPOSE_PROFILE) --env-file $(ENV_FILE) up -d

# ---------------------------------------------------------
# Stop the containers.
Expand All @@ -52,5 +42,5 @@ start: print-dot-env-files-used
.PHONY: stop
.SILENT: stop

stop: print-dot-env-files-used
docker compose --profile $(DOCKER_COMPOSE_PROFILE) --env-file $(ENV_FILE) --env-file $(SECRETS_FILE) down
stop:
docker compose --profile $(DOCKER_COMPOSE_PROFILE) --env-file $(ENV_FILE) down
32 changes: 2 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,2 @@
## `swordfish`

**Step 1.** Build the containers.
```bash
make
```

**Step 2.** Start the containers.
```bash
make start
```

**Step 3.** Create a public and private key.
```bash
openssl req -x509 -newkey rsa:2048 -keyout client.key -out client.crt -days 365 -nodes
```

**Step 4.** Create a file called `.env` and add the content below to it.
```bash
export EMASS_API_CERTIFICATE=client.crt
export EMASS_API_KEY=client.key
export EMASS_API_KEY=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
export EMASS_USER_UID=1234567890
```

**Step 5.** Run the provided script to confirm the mock eMASS API server is working.
```bash
bash demo.sh
```

# `swordfish`
For more information, [read the docs](https://deathlabs.github.io/swordfish/)!
7 changes: 4 additions & 3 deletions backend/Dockerfile → agent/openai_gpt-4o/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
FROM alpine:3.22 AS stage_1
FROM alpine:3.23
LABEL image.authors="Vic Fernandez III <@cyberphor>"
WORKDIR /home/swordfish/
COPY swordfish/ swordfish/
COPY entrypoint.sh entrypoint.sh
COPY swordfish/ swordfish/
COPY requirements.txt requirements.txt
RUN apk add --no-cache --update python3 py3-pip &&\
RUN apk add --no-cache --update python3 py3-pip uvicorn &&\

Check failure on line 7 in agent/openai_gpt-4o/Dockerfile

View workflow job for this annotation

GitHub Actions / Dockerfile Lint Check (agent/openai_gpt-4o)

DL3042 warning: Avoid use of cache directory with pip. Use `pip install --no-cache-dir <package>`

Check failure on line 7 in agent/openai_gpt-4o/Dockerfile

View workflow job for this annotation

GitHub Actions / Dockerfile Lint Check (agent/openai_gpt-4o)

DL3018 warning: Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
pip install --break-system-packages -r requirements.txt &&\
adduser -D swordfish -h /home/swordfish &&\
chown -R swordfish:swordfish /home/swordfish &&\
chmod +x entrypoint.sh
USER swordfish
EXPOSE 8181
ENTRYPOINT [ "./entrypoint.sh" ]
4 changes: 4 additions & 0 deletions agent/openai_gpt-4o/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

set -e
uvicorn swordfish.main:api --host 0.0.0.0 --port 8181
4 changes: 4 additions & 0 deletions agent/openai_gpt-4o/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fastapi
openai
mcp
strands-agents
36 changes: 36 additions & 0 deletions agent/openai_gpt-4o/swordfish/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Standard-library imports.
from os import environ

# Third-party imports.
from fastapi import FastAPI, Request
from mcp.client.sse import sse_client
from strands import Agent
from strands.models.openai import OpenAIModel
from strands.tools.mcp import MCPClient

api = FastAPI()
sse_mcp_client = MCPClient(lambda: sse_client("http://swordfish-tools:8282/sse"))
history = []

@api.post("/api/v1/")
async def respond(request: Request):
global history
request = await request.json()
with sse_mcp_client:
model = OpenAIModel(
client_args={
"api_key": environ["OPENAI_API_KEY"],
},
model_id=request.get("model", "gpt-4o"),
params={
"max_tokens": 1000,
"temperature": 0.7,
},
)

tools = sse_mcp_client.list_tools_sync()
agent = Agent(model=model, tools=tools)
agent.messages = history
response = agent(prompt=request["message"])
history = agent.messages
return response.message["content"][0]["text"]
15 changes: 15 additions & 0 deletions agent/smollm2-360m-instruct-q8_0/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM alpine:3.23
LABEL image.authors="Vic Fernandez III <@cyberphor>"
WORKDIR /home/swordfish/
COPY entrypoint.sh entrypoint.sh
COPY swordfish/ swordfish/
COPY requirements.txt requirements.txt
COPY smollm2-360m-instruct-q8_0.gguf smollm2-360m-instruct-q8_0.gguf
RUN apk add --no-cache --update build-base cmake python3 py3-pip uvicorn &&\
pip install --break-system-packages -r requirements.txt &&\
adduser -D swordfish -h /home/swordfish &&\
chown -R swordfish:swordfish /home/swordfish &&\
chmod +x entrypoint.sh
USER swordfish
EXPOSE 8181
ENTRYPOINT [ "./entrypoint.sh" ]
4 changes: 4 additions & 0 deletions agent/smollm2-360m-instruct-q8_0/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

set -e
uvicorn swordfish.main:api --host 0.0.0.0 --port 8181
2 changes: 2 additions & 0 deletions agent/smollm2-360m-instruct-q8_0/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fastapi
llama-cpp-python
Loading
Loading