├── .gitignore ├── PROJECTS ├── encrypted-p2p-chat │ ├── backend │ │ ├── app │ │ │ ├── __init__.py │ │ │ ├── api │ │ │ │ └── __init__.py │ │ │ ├── core │ │ │ │ ├── __init__.py │ │ │ │ ├── encryption │ │ │ │ │ └── __init__.py │ │ │ │ ├── passkey │ │ │ │ │ └── __init__.py │ │ │ │ ├── enums.py │ │ │ │ └── exceptions.py │ │ │ ├── schemas │ │ │ │ ├── common.py │ │ │ │ ├── rooms.py │ │ │ │ ├── surreal.py │ │ │ │ └── __init__.py │ │ │ ├── main.py │ │ │ ├── services │ │ │ │ └── __init__.py │ │ │ └── models │ │ │ │ ├── __init__.py │ │ │ │ ├── OneTimePrekey.py │ │ │ │ ├── IdentityKey.py │ │ │ │ ├── SkippedMessageKey.py │ │ │ │ ├── SignedPrekey.py │ │ │ │ ├── User.py │ │ │ │ ├── Base.py │ │ │ │ └── RatchetState.py │ │ ├── alembic │ │ │ ├── README │ │ │ ├── script.py.mako │ │ │ └── env.py │ │ ├── tests │ │ │ └── __init__.py │ │ ├── .dockerignore │ │ └── .style.yapf │ ├── frontend │ │ ├── .gitignore │ │ ├── src │ │ │ ├── services │ │ │ │ └── index.ts │ │ │ ├── websocket │ │ │ │ └── index.ts │ │ │ ├── components │ │ │ │ ├── Auth │ │ │ │ │ ├── index.ts │ │ │ │ │ └── AuthCard.tsx │ │ │ │ ├── Layout │ │ │ │ │ └── index.ts │ │ │ │ ├── Chat │ │ │ │ │ ├── index.ts │ │ │ │ │ └── OnlineStatus.tsx │ │ │ │ └── UI │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── Badge.tsx │ │ │ │ │ └── Spinner.tsx │ │ │ ├── crypto │ │ │ │ └── index.ts │ │ │ ├── vite-env.d.ts │ │ │ ├── types │ │ │ │ ├── index.ts │ │ │ │ ├── api.ts │ │ │ │ ├── auth.ts │ │ │ │ └── chat.ts │ │ │ ├── stores │ │ │ │ ├── index.ts │ │ │ │ ├── auth.store.ts │ │ │ │ ├── session.store.ts │ │ │ │ ├── presence.store.ts │ │ │ │ └── rooms.store.ts │ │ │ ├── pages │ │ │ │ ├── Login.tsx │ │ │ │ ├── Register.tsx │ │ │ │ └── NotFound.tsx │ │ │ ├── App.tsx │ │ │ ├── index.tsx │ │ │ └── config.ts │ │ ├── .prettierrc │ │ ├── .prettierignore │ │ ├── tsconfig.json │ │ ├── index.html │ │ ├── vite.config.ts │ │ ├── README.md │ │ └── package.json │ ├── conf │ │ ├── docker │ │ │ ├── dev │ │ │ │ ├── vite.docker │ │ │ │ └── fastapi.docker │ │ │ └── prod │ │ │ │ ├── vite.docker │ │ │ │ └── fastapi.docker │ │ └── nginx │ │ │ └── http.conf │ ├── .gitignore │ └── .env.example ├── Aenebris │ ├── Setup.hs │ ├── CHANGELOG.md │ ├── .gitignore │ ├── README.md │ ├── stack.yaml.lock │ ├── examples │ │ ├── config-https.yaml │ │ ├── config.yaml │ │ ├── start_backends.sh │ │ ├── config-sni.yaml │ │ ├── config-loadbalancing.yaml │ │ ├── config-advanced.yaml │ │ ├── test_backend.py │ │ ├── generate-test-certs.sh │ │ └── test_backend_multi.py │ ├── app │ │ └── Main.hs │ ├── LICENSE │ ├── .style.yapf │ ├── src │ │ └── Aenebris │ │ │ └── Middleware │ │ │ └── Redirect.hs │ ├── Makefile │ └── stack.yaml ├── dns-lookup │ ├── tests │ │ └── __init__.py │ ├── dnslookup │ │ ├── __init__.py │ │ └── __main__.py │ └── .style.yapf ├── api-security-scanner │ ├── backend │ │ ├── core │ │ │ ├── __init__.py │ │ │ ├── enums.py │ │ │ ├── database.py │ │ │ ├── dependencies.py │ │ │ └── security.py │ │ ├── routes │ │ │ ├── __init__.py │ │ │ └── auth.py │ │ ├── services │ │ │ └── __init__.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── User.py │ │ │ ├── Base.py │ │ │ ├── Scan.py │ │ │ └── TestResult.py │ │ ├── repositories │ │ │ └── __init__.py │ │ ├── main.py │ │ ├── scanners │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── requirements.txt │ │ ├── schemas │ │ │ ├── __init__.py │ │ │ ├── test_result_schemas.py │ │ │ ├── scan_schemas.py │ │ │ └── user_schemas.py │ │ ├── .style.yapf │ │ └── factory.py │ ├── frontend │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ └── site.webmanifest │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── vite-env.d.ts │ │ │ ├── main.tsx │ │ │ ├── pages │ │ │ │ ├── AuthPage.css │ │ │ │ ├── LoginPage.tsx │ │ │ │ ├── RegisterPage.tsx │ │ │ │ ├── DashboardPage.tsx │ │ │ │ └── DashboardPage.css │ │ │ ├── lib │ │ │ │ ├── queryClient.ts │ │ │ │ ├── errors.ts │ │ │ │ ├── utils.ts │ │ │ │ ├── validation.ts │ │ │ │ └── api.ts │ │ │ ├── types │ │ │ │ ├── auth.types.ts │ │ │ │ └── scan.types.ts │ │ │ ├── services │ │ │ │ ├── authService.ts │ │ │ │ └── scanService.ts │ │ │ ├── styles │ │ │ │ ├── index.css │ │ │ │ └── variables.css │ │ │ ├── components │ │ │ │ ├── common │ │ │ │ │ ├── Button.tsx │ │ │ │ │ ├── ProtectedRoute.tsx │ │ │ │ │ ├── LoadingOverlay.tsx │ │ │ │ │ ├── Input.css │ │ │ │ │ ├── Input.tsx │ │ │ │ │ ├── LoadingOverlay.css │ │ │ │ │ └── Button.css │ │ │ │ ├── scan │ │ │ │ │ └── ScanForm.css │ │ │ │ └── auth │ │ │ │ │ └── AuthForm.css │ │ │ ├── router.tsx │ │ │ └── App.tsx │ │ ├── .stylelintrc.json │ │ ├── .prettierignore │ │ ├── .gitignore │ │ ├── tsconfig.node.json │ │ ├── tsconfig.app.json │ │ ├── index.html │ │ ├── vite.config.ts │ │ ├── .prettierrc.json │ │ └── package.json │ ├── conf │ │ ├── nginx │ │ │ ├── http.conf │ │ │ └── dev.nginx │ │ └── docker │ │ │ ├── dev │ │ │ ├── vite.docker │ │ │ └── fastapi.docker │ │ │ └── prod │ │ │ ├── vite.docker │ │ │ └── fastapi.docker │ ├── .gitignore │ ├── .pre-commit-config.yaml │ ├── package.json │ └── Makefile └── keylogger │ ├── requirements.txt │ └── .style.yapf ├── .gitmodules ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── feature_request.yml │ ├── bug_report.yml │ └── project_submission.yml └── workflows │ ├── publish-dns-lookup.yml │ └── update-submodule.yml ├── CHANGELOG.rst ├── LICENSE ├── SECURITY.md └── CONTRIBUTING.rst /.gitignore: -------------------------------------------------------------------------------- 1 | cyber-proj 2 | *.cache 3 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/core/encryption/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/core/passkey/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/alembic/README: -------------------------------------------------------------------------------- 1 | Generic single database configuration 2 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | encrypted-p2p-chat pyest suite 4 | """ 5 | -------------------------------------------------------------------------------- /PROJECTS/dns-lookup/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | CarterPerez-dev | 2025 3 | __init__.py 4 | Test suite for DNS Lookup CLI 5 | """ 6 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/core/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Core modules for application infrastructure 4 | """ 5 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | dist-ssr 4 | *.local 5 | .env 6 | .DS_Store 7 | .context 8 | 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "templates/fullstack-template"] 2 | path = templates/fullstack-template 3 | url = https://github.com/CarterPerez-dev/fullstack-template 4 | -------------------------------------------------------------------------------- /PROJECTS/dns-lookup/dnslookup/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | CarterPerez-dev | 2025 3 | __init__.py 4 | """ 5 | 6 | __version__ = "0.1.1" 7 | __author__ = "CarterPerez-dev" 8 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CarterPerez-dev/Cybersecurity-Projects/HEAD/PROJECTS/api-security-scanner/frontend/public/favicon.ico -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CarterPerez-dev/Cybersecurity-Projects/HEAD/PROJECTS/api-security-scanner/frontend/public/favicon-16x16.png -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CarterPerez-dev/Cybersecurity-Projects/HEAD/PROJECTS/api-security-scanner/frontend/public/favicon-32x32.png -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CarterPerez-dev/Cybersecurity-Projects/HEAD/PROJECTS/api-security-scanner/frontend/public/apple-touch-icon.png -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CarterPerez-dev/Cybersecurity-Projects/HEAD/PROJECTS/api-security-scanner/frontend/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CarterPerez-dev/Cybersecurity-Projects/HEAD/PROJECTS/api-security-scanner/frontend/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/services/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export * from "./auth.service" 6 | export * from "./room.service" 7 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/websocket/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export * from "./websocket-manager" 6 | export * from "./message-handlers" 7 | -------------------------------------------------------------------------------- /PROJECTS/dns-lookup/dnslookup/__main__.py: -------------------------------------------------------------------------------- 1 | """ 2 | CarterPerez-dev | 2025 3 | __main__.py 4 | 5 | Entry point for python -m dnslookup 6 | """ 7 | 8 | from dnslookup.cli import app 9 | 10 | if __name__ == "__main__": 11 | app() 12 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_API_URL: string; 5 | } 6 | 7 | interface ImportMeta { 8 | readonly env: ImportMetaEnv; 9 | } 10 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "es5", 4 | "singleQuote": false, 5 | "printWidth": 95, 6 | "tabWidth": 2, 7 | "useTabs": false, 8 | "plugins": ["prettier-plugin-tailwindcss"] 9 | } 10 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/routes/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | API route handlers 3 | """ 4 | 5 | from .auth import router as auth_router 6 | from .scans import router as scans_router 7 | 8 | 9 | __all__ = [ 10 | "auth_router", 11 | "scans_router", 12 | ] 13 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-standard-scss", 4 | "stylelint-config-prettier-scss" 5 | ], 6 | "rules": { 7 | "scss/at-rule-no-unknown": null, 8 | "selector-class-pattern": null 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/Auth/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export { PasskeyButton } from "./PasskeyButton" 6 | export { AuthCard } from "./AuthCard" 7 | export { AuthForm } from "./AuthForm" 8 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/crypto/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export * from "./primitives" 6 | export * from "./key-store" 7 | export * from "./x3dh" 8 | export * from "./double-ratchet" 9 | export * from "./crypto-service" 10 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_API_URL: string 5 | readonly VITE_WS_URL: string 6 | readonly VITE_RP_ID: string 7 | } 8 | 9 | interface ImportMeta { 10 | readonly env: ImportMetaEnv 11 | } 12 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} 2 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/services/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Biz logic layer for orchestrating repositories and scanners 4 | """ 5 | 6 | from .auth_service import AuthService 7 | from .scan_service import ScanService 8 | 9 | 10 | __all__ = [ 11 | "AuthService", 12 | "ScanService", 13 | ] 14 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/Layout/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export { AppShell } from "./AppShell" 6 | export { Sidebar } from "./Sidebar" 7 | export { Header } from "./Header" 8 | export { ProtectedRoute, GuestRoute } from "./ProtectedRoute" 9 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export * from "./api" 6 | export * from "./auth" 7 | export * from "./chat" 8 | export * from "./websocket" 9 | export * from "./encryption" 10 | export * from "./components" 11 | export * from "./guards" 12 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/models/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Database models package 4 | """ 5 | 6 | from .Base import BaseModel 7 | 8 | from .User import User 9 | from .Scan import Scan 10 | from .TestResult import TestResult 11 | 12 | 13 | __all__ = [ 14 | "BaseModel", 15 | "User", 16 | "Scan", 17 | "TestResult", 18 | ] 19 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | 4 | # Build outputs 5 | dist/ 6 | build/ 7 | 8 | # Logs 9 | *.log 10 | npm-debug.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage/ 19 | 20 | # Other 21 | .DS_Store 22 | .env* 23 | .vscode/ 24 | .idea/ 25 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/conf/docker/dev/vite.docker: -------------------------------------------------------------------------------- 1 | # ©AngelaMos | 2025 2 | # Development Vite Dockerfile 3 | # HMR dev server, volume mounts for code 4 | 5 | FROM node:22-alpine 6 | 7 | WORKDIR /app 8 | 9 | COPY frontend/package*.json ./ 10 | 11 | RUN npm ci 12 | 13 | COPY frontend/ . 14 | 15 | EXPOSE 5173 16 | 17 | CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] 18 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | 4 | # Build outputs 5 | dist/ 6 | build/ 7 | 8 | # Logs 9 | *.log 10 | npm-debug.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage/ 19 | 20 | # Other 21 | .DS_Store 22 | .env* 23 | .vscode/ 24 | .idea/ 25 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog for `aenebris` 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to the 7 | [Haskell Package Versioning Policy](https://pvp.haskell.org/). 8 | 9 | ## Unreleased 10 | 11 | ## 0.1.0.0 - YYYY-MM-DD 12 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/.dockerignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.pyc 3 | *.pyo 4 | *.pyd 5 | .Python 6 | *.so 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | .env 12 | .env.* 13 | !.env.example 14 | .venv 15 | venv 16 | ENV 17 | env 18 | .pytest_cache 19 | .mypy_cache 20 | .ruff_cache 21 | .coverage 22 | htmlcov 23 | *.log 24 | .git 25 | .gitignore 26 | README.md 27 | *.md 28 | tests 29 | .vscode 30 | .idea 31 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/conf/nginx/http.conf: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Shared HTTP configuration for both dev and prod 3 | # This file contains common upstream definitions 4 | 5 | # Upstream backend (FastAPI) - used in both dev and prod 6 | upstream backend { 7 | server backend:8000; 8 | } 9 | 10 | # Upstream frontend (Vite dev server) - only used in dev 11 | upstream frontend { 12 | server frontend:5173; 13 | } 14 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/stores/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export * from "./auth.store" 6 | export * from "./session.store" 7 | export * from "./settings.store" 8 | export * from "./ui.store" 9 | export * from "./rooms.store" 10 | export * from "./messages.store" 11 | export * from "./presence.store" 12 | export * from "./typing.store" 13 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/repositories/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Database repository layer for data access operations 4 | """ 5 | 6 | from .user_repository import UserRepository 7 | from .scan_repository import ScanRepository 8 | from .test_result_repository import TestResultRepository 9 | 10 | 11 | __all__ = [ 12 | "UserRepository", 13 | "ScanRepository", 14 | "TestResultRepository", 15 | ] 16 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/main.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Application entry point 4 | */ 5 | 6 | import { StrictMode } from 'react'; 7 | import { createRoot } from 'react-dom/client'; 8 | import App from './App.tsx'; 9 | import './styles/variables.css'; 10 | import './styles/index.css'; 11 | 12 | createRoot(document.getElementById('root')!).render( 13 | 14 | 15 | , 16 | ); 17 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/.gitignore: -------------------------------------------------------------------------------- 1 | # Haskell build artifacts 2 | .stack-work/ 3 | dist/ 4 | dist-newstyle/ 5 | cabal.project.local 6 | cabal.project.local~ 7 | .HTF/ 8 | .ghc.environment.* 9 | 10 | # Editor files 11 | *.swp 12 | *.swo 13 | *~ 14 | .DS_Store 15 | 16 | # Test certificates (self-signed, regenerate with script) 17 | examples/certs/ 18 | 19 | # Logs 20 | *.log 21 | 22 | # Private progress tracking 23 | PROGRESS.md 24 | decisions.md 25 | notes.md 26 | -------------------------------------------------------------------------------- /PROJECTS/keylogger/requirements.txt: -------------------------------------------------------------------------------- 1 | # CarterPerez-dev | 2025 2 | # Keylogger requirements.txt 3 | 4 | 5 | pynput==1.8.1 6 | requests==2.32.5 7 | 8 | 9 | # Platform specific dependencies (optional but recommended) 10 | # Windows: 11 | # pywin32==311 12 | # psutil==7.1.3 13 | 14 | # macOS: 15 | # pyobjc-framework-Cocoa==12.0 16 | 17 | # Optional recommened linting 18 | # ruff==0.14.4 19 | # mypy==1.18.2 20 | # pylint==4.0.2 21 | 22 | # Optional Formatter 23 | # yapf==0.43.0 24 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/pages/AuthPage.css: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Auth page styles 4 | */ 5 | 6 | .auth-page { 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | min-height: 100vh; 11 | background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); 12 | padding: 20px; 13 | } 14 | 15 | .auth-page__container { 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | width: 100%; 20 | } 21 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/lib/queryClient.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * TanStack Query client configuration 4 | */ 5 | 6 | import { QueryClient } from '@tanstack/react-query'; 7 | 8 | export const queryClient = new QueryClient({ 9 | defaultOptions: { 10 | queries: { 11 | retry: 1, 12 | refetchOnWindowFocus: false, 13 | staleTime: 5 * 60 * 1000, // 5 minutes 14 | }, 15 | mutations: { 16 | retry: false, 17 | }, 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/pages/LoginPage.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // LoginPage.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { LoginForm } from '@/components/auth/LoginForm'; 7 | import './AuthPage.css'; 8 | 9 | export const LoginPage = (): React.ReactElement => { 10 | return ( 11 |
12 |
13 | 14 |
15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/schemas/common.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Common Pydantic schemas for API responses 4 | """ 5 | 6 | from pydantic import BaseModel 7 | 8 | 9 | class RootResponse(BaseModel): 10 | """ 11 | Root endpoint response schema 12 | """ 13 | app: str 14 | version: str 15 | status: str 16 | environment: str 17 | 18 | 19 | class HealthResponse(BaseModel): 20 | """ 21 | Health check endpoint response schema 22 | """ 23 | status: str 24 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸCertGames.com | 2025 3 | ⒸAngelaMos | CarterPerez-dev 4 | ---- 5 | API Security Scanner FastAPI entry point 6 | """ 7 | 8 | import uvicorn 9 | 10 | from config import settings 11 | from factory import create_app 12 | 13 | 14 | app = create_app() 15 | 16 | if __name__ == "__main__": 17 | uvicorn.run( 18 | "main:app", 19 | host = settings.BACKEND_HOST, 20 | port = settings.BACKEND_PORT, 21 | reload = settings.DEBUG, 22 | ) 23 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/README.md: -------------------------------------------------------------------------------- 1 | ## ⒸAngelaMos | 2025 2 | ## ⒸCertGames.com | CarterPerez-dev 3 | ---- 4 | # Ᾰenebris: Next Gen Reverse Proxy 5 | ``` 6 | ⡋⣡⣴⣶⣶⡀⠄⠄⠙⢿⣿⣿⣿⣿⣿⣴⣿⣿⣿⢃⣤⣄⣀⣥⣿ 7 | ⢸⣇⠻⣿⣿⣿⣧⣀⢀⣠⡌⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠿⣿⣿ 8 | ⢸⣿⣷⣤⣤⣤⣬⣙⣛⢿⣿⣿⣿⣿⣿⣿⡿⣿⣿⡍⠄⠄⢀⣤⣄⠉ 9 | ⣖⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⢇⣿⣿⡷⠶⠶⢿⣿⣿⠇⢀ 10 | ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⣿⣿⡇⣿⣿⣿⣿⣿⣿⣷⣶⣥⣴ 11 | ⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 12 | ⣦⣌⣛⣻⣿⣿⣧⠙⠛⠛⡭⠅⠒⠦⠭⣭⡻⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠄ 13 | ⣿⣿⣿⣿⣿⣿⣿⡆⠄⠄⠄⠄⠄⠄⠄⠄⠹⠈⢋⣽⣿⣿⣿⣿⣵⣾ 14 | ⣿⣿⣿⣿⣿⣿⣿⣿⠄⣴⣿⣶⣄⠄⣴⣶⠄⢀⣾⣿⣿⣿⣿⣿⣿⠃⠄⠄ 15 | ⠈⠻⣿⣿⣿⣿⣿⣿⡄⢻⣿⣿⣿⠄⣿⣿⡀⣾⣿⣿⣿⣿⣛⠛⠁ 16 | ⠄⠄⠈⠛⢿⣿⣿⣿⠁⠞⢿⣿⣿⡄⢿⣿⡇⣸⣿⣿⠿⠛⠁⠄ 17 | ⠄⠄⠄⠄⠄⠉⠻⣿⣿⣾⣦⡙⠻⣷⣾⣿⠃⠿⠋⠁⠄ 18 | ``` 19 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/pages/RegisterPage.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // RegisterPage.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { RegisterForm } from '@/components/auth/RegisterForm'; 7 | import './AuthPage.css'; 8 | 9 | export const RegisterPage = (): React.ReactElement => { 10 | return ( 11 |
12 |
13 | 14 |
15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/scanners/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Security scanner modules for API vulnerability testing 4 | """ 5 | 6 | from .base_scanner import BaseScanner 7 | from .rate_limit_scanner import RateLimitScanner 8 | from .auth_scanner import AuthScanner 9 | from .sqli_scanner import SQLiScanner 10 | from .idor_scanner import IDORScanner 11 | 12 | 13 | __all__ = [ 14 | "BaseScanner", 15 | "RateLimitScanner", 16 | "AuthScanner", 17 | "SQLiScanner", 18 | "IDORScanner", 19 | ] 20 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | CarterPerez-dev 3 | ⒸCertGames.com | 2025 4 | ---- 5 | API Security Scanner 6 | 7 | ⡋⣡⣴⣶⣶⡀⠄⠄⠙⢿⣿⣿⣿⣿⣿⣴⣿⣿⣿⢃⣤⣄⣀⣥⣿ 8 | ⢸⣇⠻⣿⣿⣿⣧⣀⢀⣠⡌⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠿⣿⣿ 9 | ⢸⣿⣷⣤⣤⣤⣬⣙⣛⢿⣿⣿⣿⣿⣿⣿⡿⣿⣿⡍⠄⠄⢀⣤⣄⠉ 10 | ⣖⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⢇⣿⣿⡷⠶⠶⢿⣿⣿⠇⢀ 11 | ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⣿⣿⡇⣿⣿⣿⣿⣿⣿⣷⣶⣥⣴ 12 | ⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 13 | ⣦⣌⣛⣻⣿⣿⣧⠙⠛⠛⡭⠅⠒⠦⠭⣭⡻⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠄ 14 | ⣿⣿⣿⣿⣿⣿⣿⡆⠄⠄⠄⠄⠄⠄⠄⠄⠹⠈⢋⣽⣿⣿⣿⣿⣵⣾ 15 | ⣿⣿⣿⣿⣿⣿⣿⣿⠄⣴⣿⣶⣄⠄⣴⣶⠄⢀⣾⣿⣿⣿⣿⣿⣿⠃⠄⠄ 16 | ⠈⠻⣿⣿⣿⣿⣿⣿⡄⢻⣿⣿⣿⠄⣿⣿⡀⣾⣿⣿⣿⣿⣛⠛⠁ 17 | ⠄⠄⠈⠛⢿⣿⣿⣿⠁⠞⢿⣿⣿⡄⢿⣿⡇⣸⣿⣿⠿⠛⠁⠄ 18 | ⠄⠄⠄⠄⠄⠉⠻⣿⣿⣾⣦⡙⠻⣷⣾⣿⠃⠿⠋⠁⠄ 19 | 20 | """ 21 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/pages/Login.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Login page with WebAuthn passkey authentication 3 | */ 4 | 5 | import type { JSX } from "solid-js" 6 | import { AuthForm } from "../components/Auth" 7 | import { GuestRoute } from "../components/Layout" 8 | 9 | export default function Login(): JSX.Element { 10 | return ( 11 | 12 |
13 | 14 |
15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/Chat/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export * from "./ConversationList" 6 | export * from "./ConversationItem" 7 | export * from "./MessageList" 8 | export * from "./MessageBubble" 9 | export * from "./ChatInput" 10 | export * from "./ChatHeader" 11 | export * from "./TypingIndicator" 12 | export * from "./OnlineStatus" 13 | export * from "./EncryptionBadge" 14 | export * from "./UserSearch" 15 | export * from "./NewConversation" 16 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/pages/Register.tsx: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // Registration page with WebAuthn passkey creation 4 | // =================== 5 | 6 | import type { JSX } from "solid-js" 7 | import { AuthForm } from "../components/Auth" 8 | import { GuestRoute } from "../components/Layout" 9 | 10 | export default function Register(): JSX.Element { 11 | return ( 12 | 13 |
14 | 15 |
16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/topics/lock_files 5 | 6 | packages: [] 7 | snapshots: 8 | - completed: 9 | sha256: 5524530ac8c0fd4c9d7488442ff14edb0fcbf4989b928b86398f94f367e01ee3 10 | size: 726110 11 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/19.yaml 12 | original: 13 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/19.yaml 14 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/requirements.txt: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | 3 | # FastAPI and server 4 | fastapi>=0.109.0 5 | uvicorn[standard]>=0.27.0 6 | python-multipart>=0.0.6 7 | 8 | # Database 9 | sqlalchemy>=2.0.25 10 | psycopg2-binary>=2.9.9 11 | alembic>=1.13.0 12 | 13 | # Security 14 | slowapi>=0.1.9 15 | python-jose[cryptography]>=3.3.0 16 | bcrypt==5.0.0 17 | 18 | # HTTP client for scanners 19 | requests>=2.31.0 20 | httpx>=0.26.0 21 | aiohttp>=3.9.0 22 | 23 | # Settings management 24 | pydantic>=2.5.0 25 | pydantic-settings>=2.1.0 26 | python-dotenv>=1.0.0 27 | 28 | # Utilities 29 | email-validator>=2.1.0 30 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/config-https.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | # HTTPS with single certificate + HTTP redirect 4 | listen: 5 | - port: 8080 # HTTP with redirect 6 | redirect_https: true 7 | 8 | - port: 8443 # HTTPS 9 | tls: 10 | cert: examples/certs/localhost.crt 11 | key: examples/certs/localhost.key 12 | 13 | upstreams: 14 | - name: test-backend 15 | servers: 16 | - host: "127.0.0.1:8000" 17 | weight: 1 18 | health_check: 19 | path: /health 20 | interval: 10s 21 | 22 | routes: 23 | - host: "localhost" 24 | paths: 25 | - path: / 26 | upstream: test-backend 27 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/conf/docker/prod/vite.docker: -------------------------------------------------------------------------------- 1 | # ©AngelaMos | 2025 2 | # Production Vite Dockerfile 3 | # Multi-stage: build with node, serve with nginx 4 | 5 | FROM node:22-alpine AS builder 6 | 7 | WORKDIR /app 8 | 9 | COPY frontend/package*.json ./ 10 | 11 | RUN npm ci 12 | 13 | COPY frontend/ . 14 | 15 | RUN npm run build 16 | 17 | FROM nginx:alpine 18 | 19 | COPY --from=builder /app/dist /usr/share/nginx/html 20 | 21 | COPY conf/nginx/prod.nginx /etc/nginx/nginx.conf 22 | 23 | EXPOSE 80 24 | 25 | HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 26 | CMD wget --quiet --tries=1 --spider http://localhost/health || exit 1 27 | 28 | CMD ["nginx", "-g", "daemon off;"] 29 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/UI/index.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // index.ts 4 | // =================== 5 | export { Button } from "./Button" 6 | export { Input } from "./Input" 7 | export { TextArea } from "./TextArea" 8 | export { Avatar } from "./Avatar" 9 | export { Badge } from "./Badge" 10 | export { Modal } from "./Modal" 11 | export { Spinner, LoadingOverlay } from "./Spinner" 12 | export { Toast, ToastContainer } from "./Toast" 13 | export { Skeleton, MessageSkeleton, ConversationSkeleton, AvatarSkeleton } from "./Skeleton" 14 | export { Tooltip } from "./Tooltip" 15 | export { Dropdown } from "./Dropdown" 16 | export { IconButton } from "./IconButton" 17 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/conf/docker/dev/vite.docker: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Development Vite Dockerfile 3 | # Runs Vite dev server with HMR (Hot Module Replacement) 4 | # Uses volume mounts for code (defined in docker-compose.dev.yml) 5 | 6 | FROM node:20-alpine 7 | 8 | # Set working directory 9 | WORKDIR /app 10 | 11 | # Copy package files first (for layer caching) 12 | COPY frontend/package*.json ./ 13 | 14 | # Install dependencies 15 | RUN npm ci 16 | 17 | # Copy application code (in dev this is overridden by volume mount) 18 | COPY frontend/ . 19 | 20 | # Expose port 21 | EXPOSE 5173 22 | 23 | # Run Vite dev server with --host to allow external connections 24 | CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] 25 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/.gitignore: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Gitignore - This is where you list files/folders that 3 | # should not be publicly commited to the remote repository 4 | 5 | # Python 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | *.so 10 | .Python 11 | venv/ 12 | env/ 13 | ENV/ 14 | .venv 15 | *.cache 16 | *.egg-info 17 | 18 | # FastAPI 19 | .env 20 | .env.local 21 | 22 | # Database 23 | *.db 24 | *.sqlite3 25 | 26 | # IDEs 27 | .vscode/ 28 | .idea/ 29 | *.swp 30 | *.swo 31 | 32 | # Node/Frontend 33 | node_modules/ 34 | dist/ 35 | build/ 36 | .DS_Store 37 | 38 | # Logs 39 | *.log 40 | 41 | # Testing 42 | .pytest_cache/ 43 | .coverage 44 | htmlcov/ 45 | 46 | # Docker 47 | .dockerignore 48 | 49 | # OS 50 | Thumbs.db 51 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2023", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | "moduleResolution": "bundler", 9 | "allowImportingTsExtensions": true, 10 | "verbatimModuleSyntax": true, 11 | "moduleDetection": "force", 12 | "noEmit": true, 13 | "composite": true, 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "strict": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "noFallthroughCasesInSwitch": true 20 | }, 21 | "include": ["vite.config.ts"] 22 | } 23 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Application entry point with uvicorn server command 4 | """ 5 | 6 | import uvicorn 7 | 8 | from app.config import ( 9 | DEFAULT_HOST, 10 | DEFAULT_PORT, 11 | settings, 12 | ) 13 | 14 | 15 | def main() -> None: 16 | """ 17 | Run the FastAPI application with uvicorn 18 | """ 19 | uvicorn.run( 20 | "app.factory:create_app", 21 | factory = True, 22 | host = DEFAULT_HOST, 23 | port = DEFAULT_PORT, 24 | reload = settings.is_development, 25 | log_level = "debug" if settings.DEBUG else "info", 26 | access_log = True, 27 | ) 28 | 29 | 30 | if __name__ == "__main__": 31 | main() 32 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/types/auth.types.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // auth.types.ts 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | export interface RegisterRequest { 7 | email: string; 8 | password: string; 9 | } 10 | 11 | export interface RegisterResponse { 12 | id: number; 13 | email: string; 14 | is_active: boolean; 15 | created_at: string; 16 | } 17 | 18 | export interface LoginRequest { 19 | email: string; 20 | password: string; 21 | } 22 | 23 | export interface LoginResponse { 24 | access_token: string; 25 | token_type: string; 26 | } 27 | 28 | export interface AuthUser { 29 | id: number; 30 | email: string; 31 | is_active: boolean; 32 | created_at: string; 33 | } 34 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/core/enums.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Application enums for type safety 4 | """ 5 | 6 | from enum import Enum 7 | 8 | 9 | class MessageStatus(str, Enum): 10 | """ 11 | Message delivery status 12 | """ 13 | SENDING = "sending" 14 | SENT = "sent" 15 | DELIVERED = "delivered" 16 | READ = "read" 17 | FAILED = "failed" 18 | 19 | 20 | class PresenceStatus(str, Enum): 21 | """ 22 | User presence status 23 | """ 24 | ONLINE = "online" 25 | AWAY = "away" 26 | OFFLINE = "offline" 27 | 28 | 29 | class RoomType(str, Enum): 30 | """ 31 | Chat room types 32 | """ 33 | DIRECT = "direct" 34 | GROUP = "group" 35 | EPHEMERAL = "ephemeral" 36 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/schemas/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Pydantic schemas for API validation and serialization 4 | """ 5 | 6 | from .user_schemas import ( 7 | TokenResponse, 8 | UserCreate, 9 | UserLogin, 10 | UserResponse, 11 | ) 12 | from .scan_schemas import ( 13 | ScanRequest, 14 | ScanResponse, 15 | ) 16 | from .test_result_schemas import ( 17 | TestResultCreate, 18 | TestResultResponse, 19 | ) 20 | 21 | __all__ = [ 22 | # User schemas 23 | "UserCreate", 24 | "UserLogin", 25 | "UserResponse", 26 | "TokenResponse", 27 | # Scan schemas 28 | "ScanRequest", 29 | "ScanResponse", 30 | # Test result schemas 31 | "TestResultCreate", 32 | "TestResultResponse", 33 | ] 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Provide a clear description of what this pull request does. 4 | 5 | ## Type of Change 6 | 7 | - [ ] New project idea (SYNOPSES) 8 | - [ ] Full project implementation 9 | - [ ] Bug fix 10 | - [ ] Documentation improvement 11 | - [ ] Other (please describe) 12 | 13 | ## Checklist 14 | 15 | - [ ] My code follows the existing style and conventions 16 | - [ ] I have tested my changes 17 | - [ ] I have updated relevant documentation 18 | - [ ] My changes do not introduce security vulnerabilities 19 | - [ ] I have read the CONTRIBUTING.md guidelines 20 | 21 | ## Related Issues 22 | 23 | Link any related issues here (e.g., "Fixes #123"). 24 | 25 | ## Additional Context 26 | 27 | Any other information that reviewers should know. 28 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/conf/docker/dev/fastapi.docker: -------------------------------------------------------------------------------- 1 | # ©AngelaMos | 2025 2 | # Development FastAPI Dockerfile 3 | # Hot reload with uvicorn, volume mounts for code 4 | 5 | FROM python:3.13-slim 6 | 7 | ENV PYTHONUNBUFFERED=1 \ 8 | PYTHONDONTWRITEBYTECODE=1 \ 9 | PIP_NO_CACHE_DIR=1 \ 10 | PIP_DISABLE_PIP_VERSION_CHECK=1 11 | 12 | WORKDIR /app 13 | 14 | RUN apt-get update && \ 15 | apt-get install -y --no-install-recommends \ 16 | build-essential \ 17 | libpq-dev \ 18 | curl && \ 19 | rm -rf /var/lib/apt/lists/* 20 | 21 | COPY backend/pyproject.toml ./ 22 | RUN pip install -e .[dev] 23 | 24 | COPY backend/ . 25 | 26 | EXPOSE 8000 27 | 28 | CMD ["uvicorn", "app.factory:create_app", "--factory", "--host", "0.0.0.0", "--port", "8000", "--reload"] 29 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/services/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Service layer exports 4 | """ 5 | 6 | from app.services.auth_service import AuthService, auth_service 7 | from app.services.message_service import MessageService, message_service 8 | from app.services.prekey_service import PrekeyService, prekey_service 9 | from app.services.presence_service import PresenceService, presence_service 10 | from app.services.websocket_service import WebSocketService, websocket_service 11 | 12 | 13 | __all__ = [ 14 | "AuthService", 15 | "auth_service", 16 | "MessageService", 17 | "message_service", 18 | "PrekeyService", 19 | "prekey_service", 20 | "PresenceService", 21 | "presence_service", 22 | "WebSocketService", 23 | "websocket_service", 24 | ] 25 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/core/enums.py: -------------------------------------------------------------------------------- 1 | """ 2 | Enum definitions for the application for type safety 3 | """ 4 | 5 | from enum import Enum 6 | 7 | 8 | class ScanStatus(str, Enum): 9 | """ 10 | Enum for scan result status 11 | """ 12 | 13 | VULNERABLE = "vulnerable" 14 | SAFE = "safe" 15 | ERROR = "error" 16 | 17 | 18 | class Severity(str, Enum): 19 | """ 20 | Enum for vulnerability severity levels 21 | """ 22 | 23 | CRITICAL = "critical" 24 | HIGH = "high" 25 | MEDIUM = "medium" 26 | LOW = "low" 27 | INFO = "info" 28 | 29 | 30 | class TestType(str, Enum): 31 | """ 32 | Enum for available security test types 33 | """ 34 | 35 | RATE_LIMIT = "rate_limit" 36 | AUTH = "auth" 37 | SQLI = "sqli" 38 | IDOR = "idor" 39 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/config.yaml: -------------------------------------------------------------------------------- 1 | # Ᾰenebris Configuration Example 2 | # This is a minimal working configuration for testing 3 | 4 | version: 1 5 | 6 | # Listen ports 7 | listen: 8 | - port: 8081 9 | # TLS configuration (optional) 10 | # tls: 11 | # cert: /path/to/cert.pem 12 | # key: /path/to/key.pem 13 | 14 | # Backend servers (upstreams) 15 | upstreams: 16 | - name: test-backend 17 | servers: 18 | - host: "127.0.0.1:8000" 19 | weight: 1 20 | # Health check configuration (optional) 21 | # health_check: 22 | # path: /health 23 | # interval: 10s 24 | 25 | # Routing rules 26 | routes: 27 | - host: "localhost" 28 | paths: 29 | - path: / 30 | upstream: test-backend 31 | # Rate limiting (optional) 32 | # rate_limit: 100/minute 33 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "isolatedModules": true, 12 | "moduleDetection": "force", 13 | "noEmit": true, 14 | "jsx": "preserve", 15 | "jsxImportSource": "solid-js", 16 | 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | "noUncheckedSideEffectImports": true, 22 | 23 | "baseUrl": ".", 24 | "paths": { 25 | "~/*": ["./src/*"] 26 | } 27 | }, 28 | "include": ["src"] 29 | } 30 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Changelog 3 | ========= 4 | 5 | All notable changes to this project will be documented in this file. 6 | 7 | The format is based on `Keep a Changelog `_, 8 | and this project adheres to `Semantic Versioning `_. 9 | 10 | ---- 11 | 12 | [Unreleased] 13 | ============ 14 | 15 | Aenebris Haskell Reverse Proxy work in progress 16 | ----- 17 | 18 | Changed 19 | ------- 20 | 21 | [0.3.0] - 2025-12-9 22 | ==================== 23 | 24 | Fixed some bugs in p2p-encrypted-chat, added dns-lookup tool project, added wiki pages 25 | ---- 26 | 27 | [0.2.0] - 2025-11-24 28 | ==================== 29 | 30 | Added WIP p2p-encrypted-chat 31 | ---- 32 | 33 | [0.1.0] - 2025-11-12 34 | ==================== 35 | 36 | Initial release with api-security-scanner and keylogger 37 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Encrypted P2P Chat 8 | 9 | 10 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/types/api.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // api.ts 4 | // =================== 5 | export class ApiError extends Error { 6 | constructor( 7 | public status: number, 8 | public data: unknown, 9 | message?: string 10 | ) { 11 | super(message ?? `API Error: ${status}`) 12 | this.name = "ApiError" 13 | } 14 | } 15 | 16 | export interface ApiResponse { 17 | data: T 18 | status: number 19 | } 20 | 21 | export interface PaginatedResponse { 22 | items: T[] 23 | total: number 24 | page: number 25 | pageSize: number 26 | hasMore: boolean 27 | } 28 | 29 | export interface ValidationError { 30 | field: string 31 | message: string 32 | } 33 | 34 | export interface ApiErrorResponse { 35 | detail: string | ValidationError[] 36 | status_code?: number 37 | } 38 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from typing import Sequence, Union 9 | 10 | from alembic import op 11 | import sqlalchemy as sa 12 | ${imports if imports else ""} 13 | 14 | # revision identifiers, used by Alembic. 15 | revision: str = ${repr(up_revision)} 16 | down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)} 17 | branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} 18 | depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} 19 | 20 | 21 | def upgrade() -> None: 22 | """Upgrade schema.""" 23 | ${upgrades if upgrades else "pass"} 24 | 25 | 26 | def downgrade() -> None: 27 | """Downgrade schema.""" 28 | ${downgrades if downgrades else "pass"} 29 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Database models exports 4 | """ 5 | 6 | from app.models.Base import ( 7 | BaseDBModel, 8 | engine, 9 | get_session, 10 | init_db, 11 | ) 12 | from app.models.Credential import Credential 13 | from app.models.IdentityKey import IdentityKey 14 | from app.models.OneTimePrekey import OneTimePrekey 15 | from app.models.RatchetState import RatchetState 16 | from app.models.SignedPrekey import SignedPrekey 17 | from app.models.SkippedMessageKey import SkippedMessageKey 18 | from app.models.User import User 19 | 20 | 21 | __all__ = [ 22 | "BaseDBModel", 23 | "Credential", 24 | "IdentityKey", 25 | "OneTimePrekey", 26 | "RatchetState", 27 | "SignedPrekey", 28 | "SkippedMessageKey", 29 | "User", 30 | "engine", 31 | "get_session", 32 | "init_db", 33 | ] 34 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // App.tsx 4 | // =================== 5 | import { Route } from "@solidjs/router"; 6 | import { type Component, lazy } from "solid-js"; 7 | 8 | const Home = lazy(() => import("./pages/Home")); 9 | const Register = lazy(() => import("./pages/Register")); 10 | const Login = lazy(() => import("./pages/Login")); 11 | const Chat = lazy(() => import("./pages/Chat")); 12 | const NotFound = lazy(() => import("./pages/NotFound")); 13 | 14 | const App: Component = () => { 15 | return ( 16 | <> 17 | 18 | 19 | 20 | 21 | 22 | 23 | ); 24 | }; 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { render } from "solid-js/web"; 2 | import { Router } from "@solidjs/router"; 3 | import { QueryClient, QueryClientProvider } from "@tanstack/solid-query"; 4 | import App from "./App"; 5 | import { ToastContainer } from "./components/UI/Toast"; 6 | import "./index.css"; 7 | 8 | const queryClient = new QueryClient({ 9 | defaultOptions: { 10 | queries: { 11 | refetchOnWindowFocus: false, 12 | retry: 1, 13 | staleTime: 5 * 60 * 1000, 14 | }, 15 | }, 16 | }); 17 | 18 | const root = document.getElementById("root"); 19 | 20 | if (root === null) { 21 | throw new Error("Root element not found"); 22 | } 23 | 24 | render( 25 | () => ( 26 | 27 | 28 | 29 | 30 | 31 | 32 | ), 33 | root 34 | ); 35 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 | "target": "ES2022", 5 | "useDefineForClassFields": true, 6 | "lib": ["ES2022", "DOM", "DOM.Iterable"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | "moduleResolution": "bundler", 10 | "allowImportingTsExtensions": true, 11 | "verbatimModuleSyntax": true, 12 | "moduleDetection": "force", 13 | "noEmit": true, 14 | "jsx": "react-jsx", 15 | "isolatedModules": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./src/*"] 19 | }, 20 | "strict": true, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "noFallthroughCasesInSwitch": true, 24 | "noImplicitReturns": true, 25 | "exactOptionalPropertyTypes": true 26 | }, 27 | "include": ["src"] 28 | } 29 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/services/authService.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // authService.ts 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { api } from '@/lib/api'; 7 | import { AUTH_ENDPOINTS } from '@/config/constants'; 8 | import type { 9 | LoginRequest, 10 | LoginResponse, 11 | RegisterRequest, 12 | RegisterResponse, 13 | } from '@/types/auth.types'; 14 | 15 | export const authQueryKeys = { 16 | all: ['auth'] as const, 17 | user: () => [...authQueryKeys.all, 'user'] as const, 18 | } as const; 19 | 20 | export const authMutations = { 21 | register: async (data: RegisterRequest): Promise => { 22 | return api.post(AUTH_ENDPOINTS.REGISTER, data); 23 | }, 24 | 25 | login: async (data: LoginRequest): Promise => { 26 | return api.post(AUTH_ENDPOINTS.LOGIN, data); 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/styles/index.css: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Global styles and CSS reset 4 | */ 5 | 6 | /* CSS Reset */ 7 | * { 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | } 12 | 13 | html, 14 | body { 15 | width: 100%; 16 | height: 100%; 17 | overflow-x: hidden; 18 | } 19 | 20 | body { 21 | font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', 22 | Arial, sans-serif; 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | #root { 28 | width: 100%; 29 | min-height: 100vh; 30 | } 31 | 32 | a { 33 | text-decoration: none; 34 | color: inherit; 35 | } 36 | 37 | button { 38 | border: none; 39 | background: none; 40 | cursor: pointer; 41 | font-family: inherit; 42 | } 43 | 44 | ul, 45 | ol { 46 | list-style: none; 47 | } 48 | 49 | img { 50 | max-width: 100%; 51 | height: auto; 52 | } 53 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/.gitignore: -------------------------------------------------------------------------------- 1 | # Environment 2 | /.env 3 | .env.local 4 | backend/.env 5 | frontend/.env 6 | 7 | # Python 8 | __pycache__/ 9 | *.py[cod] 10 | *$py.class 11 | *.so 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | venv/ 29 | .venv/ 30 | ENV/ 31 | env/ 32 | 33 | # Testing 34 | .pytest_cache/ 35 | .coverage 36 | htmlcov/ 37 | .mypy_cache/ 38 | .ruff_cache/ 39 | 40 | # IDE 41 | .vscode/ 42 | .idea/ 43 | *.swp 44 | *.swo 45 | *~ 46 | 47 | # Logs 48 | *.log 49 | logs/ 50 | 51 | # Docker 52 | docker-compose.override.yml 53 | 54 | # Database 55 | *.db 56 | *.sqlite 57 | *.sqlite3 58 | 59 | # macOS 60 | .DS_Store 61 | 62 | # Node 63 | node_modules/ 64 | .pnpm-store/ 65 | dist/ 66 | .solid/ 67 | 68 | # Nginx 69 | nginx/ssl/ 70 | 71 | # AI handoff documentation 72 | .truth 73 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/conf/docker/dev/fastapi.docker: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Development FastAPI Dockerfile 3 | 4 | FROM python:3.11-slim 5 | 6 | # Set environment variables 7 | ENV PYTHONUNBUFFERED=1 \ 8 | PYTHONDONTWRITEBYTECODE=1 \ 9 | PIP_NO_CACHE_DIR=1 \ 10 | PIP_DISABLE_PIP_VERSION_CHECK=1 11 | 12 | # Set working directory 13 | WORKDIR /app 14 | 15 | # Install system dependencies 16 | RUN apt-get update && apt-get install -y --no-install-recommends \ 17 | gcc \ 18 | postgresql-client \ 19 | && rm -rf /var/lib/apt/lists/* 20 | 21 | # Copy only requirements first (for layer caching) 22 | COPY backend/requirements.txt . 23 | 24 | # Install Python dependencies 25 | RUN pip install --no-cache-dir -r requirements.txt 26 | 27 | # Copy application code 28 | COPY backend/ . 29 | 30 | # Expose port 31 | EXPOSE 8000 32 | 33 | # Run with uvicorn hot reload 34 | CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] 35 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/core/database.py: -------------------------------------------------------------------------------- 1 | """ 2 | Database configuration and session management using SQLAlchemy. 3 | """ 4 | 5 | from collections.abc import Generator 6 | 7 | from sqlalchemy import create_engine 8 | from sqlalchemy.orm import Session, sessionmaker 9 | from sqlalchemy.ext.declarative import declarative_base 10 | 11 | from config import settings 12 | 13 | # Database engine 14 | engine = create_engine( 15 | settings.DATABASE_URL, 16 | pool_pre_ping = True, 17 | echo = settings.DEBUG, 18 | ) 19 | 20 | # Session factory 21 | SessionLocal = sessionmaker( 22 | autocommit = False, 23 | autoflush = False, 24 | bind = engine 25 | ) 26 | 27 | # Base class 28 | Base = declarative_base() 29 | 30 | 31 | def get_db() -> Generator[Session, None, None]: 32 | """ 33 | FastAPI dependency for database sessions 34 | """ 35 | db = SessionLocal() 36 | try: 37 | yield db 38 | finally: 39 | db.close() 40 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/pages/NotFound.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 404 Not Found page 3 | */ 4 | 5 | import type { JSX } from "solid-js" 6 | import { A } from "@solidjs/router" 7 | import { Button } from "../components/UI" 8 | 9 | export default function NotFound(): JSX.Element { 10 | return ( 11 |
12 |
13 |

14 | 404 15 |

16 | 17 |

18 | PAGE NOT FOUND 19 |

20 | 21 |

22 | THE PAGE YOU ARE LOOKING FOR DOES NOT EXIST 23 |

24 | 25 | 26 | 29 | 30 |
31 |
32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/Button.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // Button.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { type ButtonHTMLAttributes } from 'react'; 7 | import './Button.css'; 8 | 9 | interface ButtonProps extends ButtonHTMLAttributes { 10 | variant?: 'primary' | 'secondary' | 'ghost'; 11 | size?: 'sm' | 'md' | 'lg'; 12 | isLoading?: boolean; 13 | children: React.ReactNode; 14 | } 15 | 16 | export const Button = ({ 17 | variant = 'primary', 18 | size = 'md', 19 | isLoading = false, 20 | disabled, 21 | children, 22 | ...props 23 | }: ButtonProps): React.ReactElement => { 24 | return ( 25 | 33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # .pre-commit-config.yaml 2 | 3 | repos: 4 | - repo: https://github.com/astral-sh/ruff-pre-commit 5 | rev: v0.14.8 6 | hooks: 7 | - id: ruff 8 | args: ["backend/"] 9 | always_run: true 10 | 11 | - id: mypy-check 12 | name: MyPy Type Checking 13 | entry: bash -c 'cd backend && mypy .' 14 | language: system 15 | types: [python] 16 | pass_filenames: false 17 | always_run: true 18 | 19 | - id: pylint-check 20 | name: PyLint Code Quality 21 | entry: bash -c 'cd backend && pylint .' 22 | language: system 23 | types: [python] 24 | pass_filenames: false 25 | always_run: true 26 | 27 | - repo: https://github.com/pre-commit/pre-commit-hooks 28 | rev: v6.0.0 29 | hooks: 30 | - id: check-toml 31 | - id: debug-statements 32 | - id: end-of-file-fixer 33 | - id: check-yaml 34 | args: [--allow-multiple-documents] 35 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/conf/nginx/http.conf: -------------------------------------------------------------------------------- 1 | # ©AngelaMos | 2025 2 | # Shared HTTP configuration for dev and prod 3 | 4 | # WebSocket upgrade handling - sets Connection to "upgrade" when Upgrade header present, 5 | # otherwise "close" for regular HTTP requests 6 | map $http_upgrade $connection_upgrade { 7 | default upgrade; 8 | '' close; 9 | } 10 | 11 | upstream backend { 12 | server backend:8000 max_fails=3 fail_timeout=30s; 13 | keepalive 32; 14 | } 15 | 16 | upstream frontend { 17 | server frontend:5173; 18 | } 19 | 20 | log_format main_timed '$remote_addr - $remote_user [$time_local] ' 21 | '"$request" $status $body_bytes_sent ' 22 | '"$http_referer" "$http_user_agent" ' 23 | 'rt=$request_time uct="$upstream_connect_time" ' 24 | 'uht="$upstream_header_time" urt="$upstream_response_time"'; 25 | 26 | limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; 27 | limit_conn_zone $binary_remote_addr zone=conn_limit:10m; 28 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/start_backends.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Start multiple test backends for load balancing testing 3 | 4 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 5 | 6 | # Kill any existing backends 7 | pkill -f "test_backend_multi.py" || true 8 | 9 | echo "Starting 3 test backends..." 10 | 11 | # Start backend on port 8000 12 | python3 "$SCRIPT_DIR/test_backend_multi.py" 8000 > /tmp/backend-8000.log 2>&1 & 13 | echo "Backend 1 started on port 8000 (PID: $!)" 14 | 15 | # Start backend on port 8001 16 | python3 "$SCRIPT_DIR/test_backend_multi.py" 8001 > /tmp/backend-8001.log 2>&1 & 17 | echo "Backend 2 started on port 8001 (PID: $!)" 18 | 19 | # Start backend on port 8002 20 | python3 "$SCRIPT_DIR/test_backend_multi.py" 8002 > /tmp/backend-8002.log 2>&1 & 21 | echo "Backend 3 started on port 8002 (PID: $!)" 22 | 23 | echo "" 24 | echo "All backends started! Logs in /tmp/backend-*.log" 25 | echo "Test health checks:" 26 | echo " curl http://localhost:8000/health" 27 | echo " curl http://localhost:8001/health" 28 | echo " curl http://localhost:8002/health" 29 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/lib/errors.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // errors.ts 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { isAxiosError } from 'axios'; 7 | import { toast } from 'sonner'; 8 | 9 | export const createApiErrorHandler = (context: string) => { 10 | return (error: unknown): void => { 11 | if ( 12 | isAxiosError(error) && 13 | error.response?.data !== null && 14 | error.response?.data !== undefined 15 | ) { 16 | const errorData: unknown = error.response.data; 17 | 18 | if ( 19 | typeof errorData === 'object' && 20 | errorData !== null && 21 | 'detail' in errorData && 22 | typeof errorData.detail === 'string' && 23 | errorData.detail.length > 0 24 | ) { 25 | toast.error(errorData.detail); 26 | return; 27 | } 28 | } 29 | 30 | const fallbackMessage = 31 | error instanceof Error 32 | ? error.message 33 | : `Operation failed: ${context}`; 34 | toast.error(fallbackMessage); 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/config-sni.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | # HTTPS with SNI (multiple certificates for different domains) 4 | listen: 5 | - port: 8080 # HTTP with redirect 6 | redirect_https: true 7 | 8 | - port: 8443 # HTTPS with SNI 9 | tls: 10 | sni: 11 | - domain: "api.localhost" 12 | cert: examples/certs/api.localhost.crt 13 | key: examples/certs/api.localhost.key 14 | - domain: "web.localhost" 15 | cert: examples/certs/web.localhost.crt 16 | key: examples/certs/web.localhost.key 17 | default_cert: examples/certs/default.crt 18 | default_key: examples/certs/default.key 19 | 20 | upstreams: 21 | - name: api-backend 22 | servers: 23 | - host: "127.0.0.1:8001" 24 | weight: 1 25 | 26 | - name: web-backend 27 | servers: 28 | - host: "127.0.0.1:8002" 29 | weight: 1 30 | 31 | routes: 32 | - host: "api.localhost" 33 | paths: 34 | - path: / 35 | upstream: api-backend 36 | 37 | - host: "web.localhost" 38 | paths: 39 | - path: / 40 | upstream: web-backend 41 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/config-loadbalancing.yaml: -------------------------------------------------------------------------------- 1 | # Ᾰenebris Load Balancing Test Configuration 2 | # This config tests all 3 load balancing algorithms 3 | 4 | version: 1 5 | 6 | # Listen on port 8081 7 | listen: 8 | - port: 8081 9 | 10 | # Multiple backends for testing load balancing 11 | upstreams: 12 | - name: round-robin-backend 13 | servers: 14 | - host: "127.0.0.1:8000" 15 | weight: 1 16 | - host: "127.0.0.1:8001" 17 | weight: 1 18 | - host: "127.0.0.1:8002" 19 | weight: 1 20 | health_check: 21 | path: /health 22 | interval: 10s 23 | 24 | - name: weighted-backend 25 | servers: 26 | - host: "127.0.0.1:8000" 27 | weight: 5 # 5x more traffic 28 | - host: "127.0.0.1:8001" 29 | weight: 1 30 | - host: "127.0.0.1:8002" 31 | weight: 1 32 | health_check: 33 | path: /health 34 | interval: 10s 35 | 36 | # Routes 37 | routes: 38 | - host: "localhost" 39 | paths: 40 | - path: / 41 | upstream: round-robin-backend 42 | 43 | - path: /weighted 44 | upstream: weighted-backend 45 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | API Security Scanner 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/types/scan.types.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // scan.types.ts 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import type { ScanTestType, ScanStatus, Severity } from '@/config/constants'; 7 | 8 | export type { ScanTestType, ScanStatus, Severity }; 9 | 10 | export interface TestResult { 11 | id: number; 12 | scan_id: number; 13 | test_name: ScanTestType; 14 | status: ScanStatus; 15 | severity: Severity; 16 | details: string; 17 | evidence_json: Record; 18 | recommendations_json: string[]; 19 | created_at: string; 20 | } 21 | 22 | export interface Scan { 23 | id: number; 24 | user_id: number; 25 | target_url: string; 26 | scan_date: string; 27 | created_at: string; 28 | test_results: TestResult[]; 29 | } 30 | 31 | export interface CreateScanRequest { 32 | target_url: string; 33 | auth_token: string | null; 34 | tests_to_run: ScanTestType[]; 35 | max_requests: number; 36 | } 37 | 38 | export type CreateScanResponse = Scan; 39 | 40 | export type GetScansResponse = Scan[]; 41 | 42 | export type GetScanResponse = Scan; 43 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/schemas/rooms.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Pydantic schemas for rooms API 4 | """ 5 | 6 | from pydantic import BaseModel 7 | 8 | from app.core.enums import RoomType 9 | 10 | 11 | class CreateRoomRequest(BaseModel): 12 | """ 13 | Request to create a new room 14 | """ 15 | creator_id: str 16 | participant_id: str 17 | room_type: RoomType = RoomType.DIRECT 18 | 19 | 20 | class ParticipantResponse(BaseModel): 21 | """ 22 | Participant in a room 23 | """ 24 | user_id: str 25 | username: str 26 | display_name: str 27 | role: str = "member" 28 | joined_at: str 29 | 30 | 31 | class RoomAPIResponse(BaseModel): 32 | """ 33 | Room response for API 34 | """ 35 | id: str 36 | type: RoomType 37 | name: str | None = None 38 | participants: list[ParticipantResponse] 39 | unread_count: int = 0 40 | is_encrypted: bool = True 41 | created_at: str 42 | updated_at: str 43 | 44 | 45 | class RoomListResponse(BaseModel): 46 | """ 47 | List of rooms response 48 | """ 49 | rooms: list[RoomAPIResponse] 50 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/config.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // config.ts 4 | // =================== 5 | const envApiUrl: string | undefined = import.meta.env.VITE_API_URL as string | undefined; 6 | const envWsUrl: string | undefined = import.meta.env.VITE_WS_URL as string | undefined; 7 | const envRpId: string | undefined = import.meta.env.VITE_RP_ID as string | undefined; 8 | 9 | export const API_URL = envApiUrl !== undefined && envApiUrl !== "" ? envApiUrl : "http://localhost:8000"; 10 | export const WS_URL = envWsUrl !== undefined && envWsUrl !== "" ? envWsUrl : "ws://localhost:8000"; 11 | export const RP_ID = envRpId !== undefined && envRpId !== "" ? envRpId : "localhost"; 12 | 13 | export const WS_HEARTBEAT_INTERVAL = 30000; 14 | export const WS_RECONNECT_DELAY = 5000; 15 | export const MESSAGE_MAX_LENGTH = 50000; 16 | export const USERNAME_MIN_LENGTH = 3; 17 | export const USERNAME_MAX_LENGTH = 50; 18 | export const DISPLAY_NAME_MIN_LENGTH = 1; 19 | export const DISPLAY_NAME_MAX_LENGTH = 100; 20 | 21 | export const USER_SEARCH_MIN_LENGTH = 2; 22 | export const USER_SEARCH_DEFAULT_LIMIT = 10; 23 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // vite.config.ts 4 | // =================== 5 | import react from '@vitejs/plugin-react'; 6 | import tsconfigPaths from 'vite-tsconfig-paths'; 7 | import { defineConfig } from 'vite'; 8 | 9 | export default defineConfig({ 10 | plugins: [react(), tsconfigPaths()], 11 | resolve: { 12 | alias: { 13 | '@': '/src', 14 | }, 15 | extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'], 16 | }, 17 | build: { 18 | outDir: 'dist', 19 | sourcemap: false, 20 | rollupOptions: { 21 | output: { 22 | manualChunks: { 23 | vendor: ['react', 'react-dom'], 24 | router: ['react-router-dom'], 25 | query: ['@tanstack/react-query'], 26 | }, 27 | }, 28 | }, 29 | }, 30 | server: { 31 | host: '0.0.0.0', 32 | port: 5173, 33 | proxy: { 34 | '/api': { 35 | target: process.env.VITE_PROXY_TARGET || 'http://backend:8000', 36 | changeOrigin: true, 37 | rewrite: (path) => path.replace(/^\/api/, ''), 38 | }, 39 | }, 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/ProtectedRoute.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // ProtectedRoute.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { Navigate } from 'react-router-dom'; 7 | import { useAuthStore } from '@/store/authStore'; 8 | 9 | interface ProtectedRouteProps { 10 | children: React.ReactNode; 11 | } 12 | 13 | export const ProtectedRoute = ({ 14 | children, 15 | }: ProtectedRouteProps): React.ReactElement => { 16 | const { isAuthenticated, isLoading } = useAuthStore(); 17 | 18 | if (isLoading) { 19 | return ( 20 |
30 |

Loading...

31 |
32 | ); 33 | } 34 | 35 | if (!isAuthenticated) { 36 | return ( 37 | 41 | ); 42 | } 43 | 44 | return children as React.ReactElement; 45 | }; 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 CarterPerez-dev | CertGames.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/conf/docker/prod/vite.docker: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Production Vite Dockerfile (Multi-stage build) 3 | # Stage 1: Build the React app with Vite 4 | # Stage 2: Serve static files with Nginx 5 | 6 | 7 | # Stage 1: Build 8 | FROM node:20-alpine AS builder 9 | 10 | WORKDIR /app 11 | 12 | # Copy package files 13 | COPY frontend/package*.json ./ 14 | 15 | # Install dependencies 16 | RUN npm ci --only=production 17 | 18 | # Copy source code 19 | COPY frontend/ . 20 | 21 | # Build the app (creates dist/ folder with static files) 22 | RUN npm run build 23 | 24 | 25 | 26 | # Stage 2: Serve with Nginx 27 | FROM nginx:alpine 28 | 29 | # Copy built static files from builder stage 30 | COPY --from=builder /app/dist /usr/share/nginx/html 31 | 32 | # Copy nginx configurations 33 | COPY conf/nginx/prod.nginx /etc/nginx/nginx.conf 34 | COPY conf/nginx/http.conf /etc/nginx/http.conf 35 | 36 | # Expose port 37 | EXPOSE 80 38 | 39 | # Health check 40 | HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ 41 | CMD wget --quiet --tries=1 --spider http://localhost/health || exit 1 42 | 43 | # Start nginx 44 | CMD ["nginx", "-g", "daemon off;"] 45 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/router.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Application routing configuration 4 | */ 5 | 6 | import { createBrowserRouter, Navigate } from 'react-router-dom'; 7 | import { LoginPage } from '@/pages/LoginPage'; 8 | import { RegisterPage } from '@/pages/RegisterPage'; 9 | import { DashboardPage } from '@/pages/DashboardPage'; 10 | import { ScanResultsPage } from '@/pages/ScanResultsPage'; 11 | import { ProtectedRoute } from '@/components/common/ProtectedRoute'; 12 | 13 | export const router = createBrowserRouter([ 14 | { 15 | path: '/login', 16 | element: , 17 | }, 18 | { 19 | path: '/register', 20 | element: , 21 | }, 22 | { 23 | path: '/', 24 | element: ( 25 | 26 | 27 | 28 | ), 29 | }, 30 | { 31 | path: '/scans/:id', 32 | element: ( 33 | 34 | 35 | 36 | ), 37 | }, 38 | { 39 | path: '*', 40 | element: ( 41 | 45 | ), 46 | }, 47 | ]); 48 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // vite.config.ts 4 | // =================== 5 | import { defineConfig } from "vite"; 6 | import solid from "vite-plugin-solid"; 7 | import tailwindcss from "@tailwindcss/vite"; 8 | import path from "path"; 9 | 10 | export default defineConfig({ 11 | plugins: [solid(), tailwindcss()], 12 | envDir: "../", 13 | resolve: { 14 | alias: { 15 | "~": path.resolve(__dirname, "./src"), 16 | }, 17 | }, 18 | server: { 19 | port: 5173, 20 | host: true, 21 | proxy: { 22 | "/api": { 23 | target: "http://backend:8000", 24 | changeOrigin: true, 25 | }, 26 | "/ws": { 27 | target: "ws://backend:8000", 28 | ws: true, 29 | }, 30 | }, 31 | }, 32 | build: { 33 | target: "esnext", 34 | outDir: "dist", 35 | sourcemap: true, 36 | rollupOptions: { 37 | output: { 38 | manualChunks: { 39 | "solid-js": ["solid-js"], 40 | "solid-router": ["@solidjs/router"], 41 | "solid-query": ["@tanstack/solid-query"], 42 | }, 43 | }, 44 | }, 45 | }, 46 | }); 47 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/models/User.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | User model for authentication and user management 4 | """ 5 | 6 | from sqlalchemy import ( 7 | Boolean, 8 | Column, 9 | String, 10 | ) 11 | 12 | from config import settings 13 | from .Base import BaseModel 14 | 15 | 16 | class User(BaseModel): 17 | """ 18 | Stores authentication credentials and user information 19 | """ 20 | 21 | __tablename__ = "users" 22 | 23 | email = Column( 24 | String(settings.EMAIL_MAX_LENGTH), 25 | unique = True, 26 | nullable = False, 27 | index = True, 28 | ) 29 | hashed_password = Column(String, nullable = False) 30 | is_active = Column(Boolean, default = True, nullable = False) 31 | 32 | def __repr__(self) -> str: 33 | """ 34 | String representation of User 35 | """ 36 | return f"" 37 | 38 | @property 39 | def is_authenticated(self) -> bool: 40 | """ 41 | Check if user is active and authenticated 42 | 43 | Returns: 44 | bool: True if user is active 45 | """ 46 | return self.is_active 47 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/App.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Main application component 4 | */ 5 | 6 | import { useEffect } from 'react'; 7 | import { QueryClientProvider } from '@tanstack/react-query'; 8 | import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; 9 | import { RouterProvider } from 'react-router-dom'; 10 | import { Toaster } from 'sonner'; 11 | import { queryClient } from '@/lib/queryClient'; 12 | import { router } from '@/router'; 13 | import { useAuthStore } from '@/store/authStore'; 14 | 15 | const AuthInitializer = (): null => { 16 | const loadUserFromStorage = useAuthStore( 17 | (state) => state.loadUserFromStorage, 18 | ); 19 | 20 | useEffect(() => { 21 | loadUserFromStorage(); 22 | }, [loadUserFromStorage]); 23 | 24 | return null; 25 | }; 26 | 27 | function App(): React.ReactElement { 28 | return ( 29 | 30 | 31 | 32 | 38 | 39 | 40 | ); 41 | } 42 | 43 | export default App; 44 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/README.md: -------------------------------------------------------------------------------- 1 | # Encrypted P2P Chat - Frontend 2 | 3 | SolidJS frontend with Vite, TypeScript, and Tailwind CSS v4. 4 | 5 | ## Requirements 6 | 7 | - **Node.js 20.19+ or 22.12+** (required for Vite 7) 8 | 9 | ## Tech Stack 10 | 11 | - **SolidJS 1.9.10** - Fine-grained reactivity 12 | - **TypeScript 5.9** - Type safety 13 | - **Vite 7** - Build tool (ESM only, requires Node 20.19+) 14 | - **Tailwind CSS v4.1** - Utility-first CSS (stable release) 15 | - **@solidjs/router** - Client-side routing 16 | - **@tanstack/solid-query 5.90** - Data fetching and caching 17 | - **nanostores 1.1** - State management 18 | 19 | ## Development 20 | 21 | ```bash 22 | npm install 23 | npm run dev 24 | ``` 25 | 26 | Frontend runs on http://localhost:3000 27 | 28 | ## Build 29 | 30 | ```bash 31 | npm run build 32 | ``` 33 | 34 | Output in `dist/` directory. 35 | 36 | ## SolidJS Routing 37 | 38 | Unlike React Router, SolidJS uses: 39 | - `` component for navigation (not ``) 40 | - `useNavigate()` for programmatic navigation 41 | - `useParams()` for route parameters 42 | - `useSearchParams()` for query parameters 43 | 44 | ## Environment Variables 45 | 46 | Copy `.env.example` to `.env` and configure: 47 | 48 | - `VITE_API_URL` - Backend API URL 49 | - `VITE_WS_URL` - WebSocket URL 50 | - `VITE_RP_ID` - WebAuthn Relying Party ID 51 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // utils.ts 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | export const formatDate = (dateString: string): string => { 7 | const date = new Date(dateString); 8 | return date.toLocaleDateString('en-US', { 9 | month: 'short', 10 | day: 'numeric', 11 | year: 'numeric', 12 | }); 13 | }; 14 | 15 | export const formatDateTime = (dateString: string): string => { 16 | const date = new Date(dateString); 17 | return date.toLocaleString('en-US', { 18 | month: 'short', 19 | day: 'numeric', 20 | year: 'numeric', 21 | hour: 'numeric', 22 | minute: '2-digit', 23 | }); 24 | }; 25 | 26 | export const formatRelativeTime = (dateString: string): string => { 27 | const date = new Date(dateString); 28 | const now = new Date(); 29 | const diffMs = now.getTime() - date.getTime(); 30 | const diffMins = Math.floor(diffMs / 60000); 31 | const diffHours = Math.floor(diffMs / 3600000); 32 | const diffDays = Math.floor(diffMs / 86400000); 33 | 34 | if (diffMins < 1) return 'just now'; 35 | if (diffMins < 60) return `${diffMins.toString()}m ago`; 36 | if (diffHours < 24) return `${diffHours.toString()}h ago`; 37 | if (diffDays < 7) return `${diffDays.toString()}d ago`; 38 | 39 | return formatDate(dateString); 40 | }; 41 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/OneTimePrekey.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | X3DH one time prekey model for single use key exchange 4 | """ 5 | 6 | from typing import TYPE_CHECKING 7 | from uuid import UUID 8 | 9 | from sqlmodel import Field 10 | 11 | from app.config import ONE_TIME_PREKEY_LENGTH 12 | from app.models.Base import BaseDBModel 13 | 14 | if TYPE_CHECKING: 15 | pass 16 | 17 | 18 | class OneTimePrekey(BaseDBModel, table = True): 19 | """ 20 | X25519 one time prekey consumed after single use for X3DH protocol 21 | """ 22 | __tablename__ = "one_time_prekeys" 23 | 24 | id: int = Field(default = None, primary_key = True) 25 | user_id: UUID = Field( 26 | foreign_key = "users.id", 27 | nullable = False, 28 | index = True 29 | ) 30 | 31 | key_id: int = Field(nullable = False, index = True) 32 | 33 | public_key: str = Field(nullable = False, max_length = ONE_TIME_PREKEY_LENGTH) 34 | private_key: str = Field( 35 | nullable = False, 36 | max_length = ONE_TIME_PREKEY_LENGTH 37 | ) 38 | 39 | is_used: bool = Field(default = False, nullable = False, index = True) 40 | 41 | def __repr__(self) -> str: 42 | """ 43 | String representation of OneTimePrekey 44 | """ 45 | return f"" 46 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest a new project idea or improvement 3 | title: "[FEATURE] " 4 | labels: ["enhancement"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ## Feature Request 10 | Thanks for suggesting an improvement or new project idea. 11 | 12 | - type: textarea 13 | id: description 14 | attributes: 15 | label: Description 16 | description: A clear description of what you want to add or improve. 17 | placeholder: Describe your idea 18 | validations: 19 | required: true 20 | 21 | - type: dropdown 22 | id: category 23 | attributes: 24 | label: Project Category 25 | options: 26 | - Beginner 27 | - Intermediate 28 | - Advanced 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | id: rationale 34 | attributes: 35 | label: Rationale 36 | description: Why would this be valuable to the repository? 37 | validations: 38 | required: true 39 | 40 | - type: textarea 41 | id: technical 42 | attributes: 43 | label: Technical Details 44 | description: Any technical considerations or requirements. 45 | 46 | - type: textarea 47 | id: context 48 | attributes: 49 | label: Additional Context 50 | description: Any other relevant information. 51 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/IdentityKey.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | X3DH identity key model for long term user identification 4 | """ 5 | 6 | from typing import TYPE_CHECKING 7 | from uuid import UUID 8 | 9 | from sqlmodel import Field 10 | 11 | from app.config import IDENTITY_KEY_LENGTH 12 | from app.models.Base import BaseDBModel 13 | 14 | if TYPE_CHECKING: 15 | pass 16 | 17 | 18 | class IdentityKey(BaseDBModel, table = True): 19 | """ 20 | Long term X25519 identity key for X3DH protocol 21 | """ 22 | __tablename__ = "identity_keys" 23 | 24 | id: int = Field(default = None, primary_key = True) 25 | user_id: UUID = Field( 26 | foreign_key = "users.id", 27 | nullable = False, 28 | unique = True, 29 | index = True 30 | ) 31 | 32 | public_key: str = Field(nullable = False, max_length = IDENTITY_KEY_LENGTH) 33 | private_key: str = Field(nullable = False, max_length = IDENTITY_KEY_LENGTH) 34 | 35 | public_key_ed25519: str = Field( 36 | nullable = False, 37 | max_length = IDENTITY_KEY_LENGTH 38 | ) 39 | private_key_ed25519: str = Field( 40 | nullable = False, 41 | max_length = IDENTITY_KEY_LENGTH 42 | ) 43 | 44 | def __repr__(self) -> str: 45 | """ 46 | String representation of IdentityKey 47 | """ 48 | return f"" 49 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/LoadingOverlay.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // LoadingOverlay.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { TEST_TYPE_LABELS, type ScanTestType } from '@/config/constants'; 7 | import './LoadingOverlay.css'; 8 | 9 | interface LoadingOverlayProps { 10 | tests: ScanTestType[]; 11 | } 12 | 13 | export const LoadingOverlay = ({ 14 | tests, 15 | }: LoadingOverlayProps): React.ReactElement => { 16 | return ( 17 |
22 |
23 |
24 |
25 |
26 |

Running Security Scan

27 |

28 | Testing {tests.length}{' '} 29 | {tests.length === 1 ? 'vulnerability' : 'vulnerabilities'} 30 |

31 |
32 | {tests.map((test) => ( 33 |
37 | {TEST_TYPE_LABELS[test]} 38 |
39 | ))} 40 |
41 |
42 |
43 | ); 44 | }; 45 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-security-scanner", 3 | "version": "1.0.0", 4 | "description": "Automated API security testing tool with FastAPI backend and ReactTS frontend", 5 | "private": true, 6 | "scripts": { 7 | "dev": "docker-compose -f docker-compose.dev.yml up", 8 | "dev:build": "docker compose -f docker-compose.dev.yml up --build", 9 | "dev:down": "docker compose -f docker-compose.dev.yml down", 10 | "dev:logs": "docker compose -f docker-compose.dev.yml logs -f", 11 | "prod": "docker compose -f docker-compose.prod.yml up -d", 12 | "prod:build": "docker compose -f docker-compose.prod.yml up --build -d", 13 | "prod:down": "docker compose -f docker-compose.prod.yml down", 14 | "prod:logs": "docker compose -f docker-compose.prod.yml logs -f", 15 | "clean": "docker compose -f docker-compose.dev.yml down -v && docker compose -f docker-compose.prod.yml down -v", 16 | "clean:all": "npm run clean && docker system prune -af --volumes" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/carterperez-dev/api-security-scanner" 21 | }, 22 | "keywords": [ 23 | "security", 24 | "api-testing", 25 | "vulnerability-scanner", 26 | "pentesting", 27 | "fastapi", 28 | "react", 29 | "docker" 30 | ], 31 | "author": "CarerPerez-dev - also replace my github url username with yours", 32 | "license": "MIT" 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/publish-dns-lookup.yml: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # AngelaMos | 2025 3 | # publish-dns-lookup.yml 4 | # ============================================================================= 5 | 6 | name: Publish dns-lookup to PyPI 7 | 8 | on: 9 | push: 10 | branches: 11 | - main 12 | paths: 13 | - 'PROJECTS/dns-lookup/**' 14 | - '!PROJECTS/dns-lookup/README.md' 15 | - '!PROJECTS/dns-lookup/justfile' 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | pypi-publish: 22 | name: Upload dns-lookup to PyPI 23 | runs-on: ubuntu-latest 24 | environment: 25 | name: pypi 26 | url: https://pypi.org/p/dnslookup-cli 27 | permissions: 28 | id-token: write 29 | steps: 30 | - name: Checkout code 31 | uses: actions/checkout@v4 32 | 33 | - name: Set up Python 34 | uses: actions/setup-python@v5 35 | with: 36 | python-version: "3.13" 37 | 38 | - name: Install build dependencies 39 | run: | 40 | python -m pip install --upgrade pip 41 | pip install build 42 | 43 | - name: Build package 44 | working-directory: PROJECTS/dns-lookup 45 | run: python -m build 46 | 47 | - name: Publish to PyPI 48 | uses: pypa/gh-action-pypi-publish@release/v1 49 | with: 50 | packages-dir: PROJECTS/dns-lookup/dist/ 51 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/Input.css: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Input component styles 4 | */ 5 | 6 | .input-wrapper { 7 | display: flex; 8 | flex-direction: column; 9 | gap: 8px; 10 | width: 100%; 11 | } 12 | 13 | .input-label { 14 | font-size: 14px; 15 | font-weight: 500; 16 | color: #fff; 17 | letter-spacing: 0.01em; 18 | } 19 | 20 | .input { 21 | width: 100%; 22 | padding: 12px 16px; 23 | font-size: 16px; 24 | font-family: inherit; 25 | color: #fff; 26 | background: rgb(255 255 255 / 5%); 27 | border: 1px solid rgb(255 255 255 / 20%); 28 | border-radius: 8px; 29 | transition: all 0.2s ease; 30 | backdrop-filter: blur(10px); 31 | } 32 | 33 | .input::placeholder { 34 | color: rgb(255 255 255 / 50%); 35 | } 36 | 37 | .input:focus { 38 | outline: none; 39 | border-color: #3b82f6; 40 | background: rgb(255 255 255 / 10%); 41 | box-shadow: 0 0 0 3px rgb(59 130 246 / 10%); 42 | } 43 | 44 | .input:disabled { 45 | opacity: 0.5; 46 | cursor: not-allowed; 47 | } 48 | 49 | .input:hover:not(:disabled) { 50 | border-color: rgb(255 255 255 / 30%); 51 | background: rgb(255 255 255 / 8%); 52 | } 53 | 54 | .input--error { 55 | border-color: #ef4444; 56 | } 57 | 58 | .input--error:focus { 59 | border-color: #ef4444; 60 | box-shadow: 0 0 0 3px rgb(239 68 68 / 10%); 61 | } 62 | 63 | .input-error { 64 | font-size: 14px; 65 | color: #ef4444; 66 | margin: 0; 67 | } 68 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/services/scanService.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // scanService.ts 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { api } from '@/lib/api'; 7 | import type { 8 | CreateScanRequest, 9 | CreateScanResponse, 10 | GetScansResponse, 11 | GetScanResponse, 12 | } from '@/types/scan.types'; 13 | import { SCAN_ENDPOINTS } from '@/config/constants'; 14 | 15 | export const scanQueryKeys = { 16 | all: ['scans'] as const, 17 | 18 | lists: () => [...scanQueryKeys.all, 'list'] as const, 19 | list: () => [...scanQueryKeys.lists()] as const, 20 | 21 | details: () => [...scanQueryKeys.all, 'detail'] as const, 22 | detail: (id: number) => [...scanQueryKeys.details(), id] as const, 23 | } as const; 24 | 25 | export const scanQueries = { 26 | getScans: async (): Promise => { 27 | return api.get(SCAN_ENDPOINTS.LIST); 28 | }, 29 | 30 | getScan: async (id: number): Promise => { 31 | return api.get(SCAN_ENDPOINTS.GET(id)); 32 | }, 33 | }; 34 | 35 | export const scanMutations = { 36 | createScan: async ( 37 | data: CreateScanRequest, 38 | ): Promise => { 39 | return api.post(SCAN_ENDPOINTS.CREATE, data); 40 | }, 41 | 42 | deleteScan: async (id: number): Promise => { 43 | await api.delete(SCAN_ENDPOINTS.DELETE(id)); 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | ## Reporting Security Issues 3 | If you discover a security vulnerability in any of the projects or code in this repository, please report it responsibly. 4 | ### How to Report 5 | Send an email to:
Carterperez@certgames.com 6 | - A description of the vulnerability 7 | - Steps to reproduce the issue 8 | - Potential impact 9 | - Any suggested fixes (optional) 10 | Please do not open public issues for security vulnerabilities. 11 | ## Response Timeline 12 | We will acknowledge receipt of your report within 48 hours and provide a more detailed response within 5 business days. 13 | ## Scope 14 | This security policy applies to: 15 | - Code in the /PROJECTS directory 16 | - Project descriptions and instructions 17 | - Any scripts or tools provided in this repository 18 | ## Educational Purpose 19 | Many projects in this repository are designed for educational and ethical security research. All tools and code should only be used: 20 | - On systems you own or have explicit permission to test 21 | - In controlled lab environments 22 | - For legal security research and learning 23 | Misuse of these tools for unauthorized access or malicious purposes is prohibited and may be illegal. 24 | ## Disclaimer 25 | The maintainers of this repository are not responsible for any misuse of the code or projects provided here. Users assume all responsibility for ensuring their use complies with applicable laws and regulations. 26 | 27 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/conf/docker/prod/fastapi.docker: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Production FastAPI Dockerfile 3 | # Optimized for performance with gunicorn multi-worker setup 4 | # No hot reload, built image (no volume mounts) 5 | 6 | FROM python:3.11-slim 7 | 8 | # Set environment variables 9 | ENV PYTHONUNBUFFERED=1 \ 10 | PYTHONDONTWRITEBYTECODE=1 \ 11 | PIP_NO_CACHE_DIR=1 \ 12 | PIP_DISABLE_PIP_VERSION_CHECK=1 13 | 14 | # Set working directory 15 | WORKDIR /app 16 | 17 | # Install system dependencies 18 | RUN apt-get update && apt-get install -y --no-install-recommends \ 19 | gcc \ 20 | postgresql-client \ 21 | && rm -rf /var/lib/apt/lists/* 22 | 23 | # Copy only requirements first (for layer caching) 24 | COPY backend/requirements.txt . 25 | 26 | # Install Python dependencies 27 | RUN pip install --no-cache-dir -r requirements.txt 28 | 29 | # Install gunicorn for production 30 | RUN pip install --no-cache-dir gunicorn 31 | 32 | # Copy application code 33 | COPY backend/ . 34 | 35 | # Create non-root user for security 36 | RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app 37 | USER appuser 38 | 39 | # Expose port 40 | EXPOSE 8000 41 | 42 | # Run with gunicorn (4 workers, uvicorn worker class for async support) 43 | CMD ["gunicorn", "main:app", \ 44 | "--workers", "4", \ 45 | "--worker-class", "uvicorn.workers.UvicornWorker", \ 46 | "--bind", "0.0.0.0:8000", \ 47 | "--access-logfile", "-", \ 48 | "--error-logfile", "-"] 49 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/SkippedMessageKey.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Skipped message key storage for out of order Double Ratchet messages 4 | """ 5 | 6 | from typing import TYPE_CHECKING 7 | 8 | from sqlmodel import Field 9 | 10 | from app.models.Base import BaseDBModel 11 | from app.config import RATCHET_STATE_MAX_LENGTH 12 | 13 | if TYPE_CHECKING: 14 | pass 15 | 16 | 17 | class SkippedMessageKey(BaseDBModel, table = True): 18 | """ 19 | Stores message keys for out of order messages in Double Ratchet 20 | """ 21 | __tablename__ = "skipped_message_keys" 22 | 23 | id: int = Field(default = None, primary_key = True) 24 | 25 | ratchet_state_id: int = Field( 26 | foreign_key = "ratchet_states.id", 27 | nullable = False, 28 | index = True 29 | ) 30 | 31 | dh_public_key: str = Field( 32 | nullable = False, 33 | max_length = RATCHET_STATE_MAX_LENGTH, 34 | index = True 35 | ) 36 | message_number: int = Field(nullable = False, index = True) 37 | 38 | message_key: str = Field( 39 | nullable = False, 40 | max_length = RATCHET_STATE_MAX_LENGTH 41 | ) 42 | 43 | def __repr__(self) -> str: 44 | """ 45 | String representation of SkippedMessageKey 46 | """ 47 | return ( 48 | f"" 51 | ) 52 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/app/Main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | 3 | module Main (main) where 4 | 5 | import Aenebris.Config 6 | import Aenebris.Proxy 7 | import Network.HTTP.Client (newManager, defaultManagerSettings) 8 | import System.Environment (getArgs) 9 | import System.Exit (exitFailure) 10 | import System.IO (hPutStrLn, stderr) 11 | 12 | main :: IO () 13 | main = do 14 | args <- getArgs 15 | 16 | -- Get config file path from args or use default 17 | let configPath = case args of 18 | (path:_) -> path 19 | [] -> "config.yaml" 20 | 21 | putStrLn $ "Loading configuration from: " ++ configPath 22 | 23 | result <- loadConfig configPath 24 | case result of 25 | Left err -> do 26 | hPutStrLn stderr $ "ERROR: Failed to load configuration" 27 | hPutStrLn stderr err 28 | exitFailure 29 | 30 | Right config -> do 31 | case validateConfig config of 32 | Left err -> do 33 | hPutStrLn stderr $ "ERROR: Invalid configuration" 34 | hPutStrLn stderr err 35 | exitFailure 36 | 37 | Right () -> do 38 | putStrLn "Configuration loaded and validated successfully" 39 | 40 | -- Create HTTP client manager with connection pooling 41 | manager <- newManager defaultManagerSettings 42 | 43 | -- Initialize proxy state (load balancers + health checkers) 44 | proxyState <- initProxyState config manager 45 | 46 | -- Start the proxy 47 | startProxy proxyState 48 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "encrypted-p2p-chat-frontend", 3 | "version": "1.0.0", 4 | "description": "End-to-end encrypted P2P chat frontend with SolidJS", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "typecheck": "tsc --noEmit", 11 | "lint:eslint": "eslint .", 12 | "lint:eslint:fix": "eslint . --fix", 13 | "lint:types": "tsc --noEmit", 14 | "lint": "npm run lint:eslint && npm run lint:types", 15 | "format": "prettier --write \"src/**/*.{ts,tsx,css}\"", 16 | "format:check": "prettier --check \"src/**/*.{ts,tsx,css}\"" 17 | }, 18 | "dependencies": { 19 | "@nanostores/persistent": "^1.2.0", 20 | "@nanostores/solid": "^1.1.1", 21 | "@solidjs/router": "^0.15.3", 22 | "@tanstack/solid-query": "^5.90.13", 23 | "nanostores": "^1.1.0", 24 | "solid-js": "^1.9.10" 25 | }, 26 | "devDependencies": { 27 | "@eslint/js": "^9.17.0", 28 | "@tailwindcss/vite": "^4.1.17", 29 | "@types/node": "^22.10.2", 30 | "eslint": "^9.17.0", 31 | "eslint-config-prettier": "^10.1.5", 32 | "eslint-plugin-jsx-a11y": "^6.10.2", 33 | "eslint-plugin-solid": "^0.14.5", 34 | "globals": "^16.2.0", 35 | "prettier": "^3.4.2", 36 | "prettier-plugin-tailwindcss": "^0.6.9", 37 | "tailwindcss": "^4.1.17", 38 | "typescript": "^5.9.3", 39 | "typescript-eslint": "^8.20.0", 40 | "vite": "^7.2.4", 41 | "vite-plugin-solid": "^2.11.10" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/update-submodule.yml: -------------------------------------------------------------------------------- 1 | name: Update Submodule 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | update: 10 | name: Update fullstack-template 11 | runs-on: ubuntu-latest 12 | 13 | permissions: 14 | contents: write 15 | pull-requests: write 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v4 20 | with: 21 | submodules: true 22 | token: ${{ secrets.GITHUB_TOKEN }} 23 | 24 | - name: Update submodule to latest 25 | run: | 26 | git submodule update --remote templates/fullstack-template 27 | 28 | - name: Check for changes 29 | id: changes 30 | run: | 31 | if git diff --quiet; then 32 | echo "has_changes=false" >> $GITHUB_OUTPUT 33 | else 34 | echo "has_changes=true" >> $GITHUB_OUTPUT 35 | fi 36 | 37 | - name: Create Pull Request 38 | if: steps.changes.outputs.has_changes == 'true' 39 | uses: peter-evans/create-pull-request@v5 40 | with: 41 | commit-message: "chore: update fullstack-template submodule" 42 | title: "chore: update fullstack-template submodule" 43 | body: | 44 | Automated update of the `fullstack-template` submodule to the latest commit. 45 | 46 | This PR was created automatically by the update-submodule workflow. 47 | branch: auto/update-fullstack-template 48 | delete-branch: true 49 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/conf/docker/prod/fastapi.docker: -------------------------------------------------------------------------------- 1 | # ©AngelaMos | 2025 2 | # Production FastAPI Dockerfile 3 | # Multi stage build, gunicorn with uvicorn workers 4 | 5 | FROM python:3.13-slim AS builder 6 | 7 | ENV PYTHONUNBUFFERED=1 \ 8 | PYTHONDONTWRITEBYTECODE=1 \ 9 | PIP_NO_CACHE_DIR=1 \ 10 | PIP_DISABLE_PIP_VERSION_CHECK=1 11 | 12 | WORKDIR /app 13 | 14 | RUN apt-get update && \ 15 | apt-get install -y --no-install-recommends \ 16 | build-essential \ 17 | libpq-dev && \ 18 | rm -rf /var/lib/apt/lists/* 19 | 20 | COPY backend/pyproject.toml ./ 21 | RUN pip install --user --no-warn-script-location . 22 | RUN pip install --user --no-warn-script-location gunicorn 23 | 24 | FROM python:3.13-slim 25 | 26 | WORKDIR /app 27 | 28 | RUN apt-get update && \ 29 | apt-get install -y --no-install-recommends \ 30 | libpq5 \ 31 | curl && \ 32 | rm -rf /var/lib/apt/lists/* && \ 33 | useradd -m -u 1000 appuser 34 | 35 | COPY --from=builder /root/.local /home/appuser/.local 36 | ENV PATH=/home/appuser/.local/bin:$PATH 37 | 38 | COPY backend/ . 39 | 40 | RUN chown -R appuser:appuser /app 41 | USER appuser 42 | 43 | EXPOSE 8000 44 | 45 | HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ 46 | CMD curl -f http://localhost:8000/health || exit 1 47 | 48 | CMD ["gunicorn", "app.main:app", \ 49 | "--workers", "4", \ 50 | "--worker-class", "uvicorn.workers.UvicornWorker", \ 51 | "--bind", "0.0.0.0:8000", \ 52 | "--access-logfile", "-", \ 53 | "--error-logfile", "-"] 54 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/LICENSE: -------------------------------------------------------------------------------- 1 | ⒸAngelaMos | 2025 2 | CarterPerez-dev | CertGames.com 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/SignedPrekey.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | X3DH signed prekey model for medium term key rotation 4 | """ 5 | 6 | from datetime import datetime 7 | from typing import TYPE_CHECKING 8 | from uuid import UUID 9 | 10 | from sqlalchemy import DateTime 11 | from sqlmodel import Field 12 | 13 | from app.config import SIGNATURE_LENGTH, SIGNED_PREKEY_LENGTH 14 | from app.models.Base import BaseDBModel 15 | 16 | if TYPE_CHECKING: 17 | pass 18 | 19 | 20 | class SignedPrekey(BaseDBModel, table = True): 21 | """ 22 | X25519 signed prekey rotated every 48 hours for X3DH protocol 23 | """ 24 | __tablename__ = "signed_prekeys" 25 | 26 | id: int = Field(default = None, primary_key = True) 27 | user_id: UUID = Field( 28 | foreign_key = "users.id", 29 | nullable = False, 30 | index = True 31 | ) 32 | 33 | key_id: int = Field(nullable = False, index = True) 34 | 35 | public_key: str = Field(nullable = False, max_length = SIGNED_PREKEY_LENGTH) 36 | private_key: str = Field(nullable = False, max_length = SIGNED_PREKEY_LENGTH) 37 | 38 | signature: str = Field(nullable = False, max_length = SIGNATURE_LENGTH) 39 | 40 | is_active: bool = Field(default = True, nullable = False) 41 | expires_at: datetime | None = Field( 42 | default = None, 43 | sa_type = DateTime(timezone = True), 44 | ) 45 | 46 | def __repr__(self) -> str: 47 | """ 48 | String representation of SignedPrekey 49 | """ 50 | return f"" 51 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/routes/auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | ©AngelaMos | 2025 3 | Authentication routes 4 | """ 5 | 6 | from fastapi import ( 7 | APIRouter, 8 | Depends, 9 | Request, 10 | status, 11 | ) 12 | from slowapi import Limiter 13 | from slowapi.util import get_remote_address 14 | from sqlalchemy.orm import Session 15 | 16 | from config import settings 17 | from core.database import get_db 18 | from schemas.user_schemas import ( 19 | TokenResponse, 20 | UserCreate, 21 | UserLogin, 22 | UserResponse, 23 | ) 24 | from services.auth_service import AuthService 25 | 26 | 27 | router = APIRouter(prefix="/auth", tags=["authentication"]) 28 | limiter = Limiter(key_func=get_remote_address) 29 | 30 | 31 | @router.post( 32 | "/register", 33 | response_model=UserResponse, 34 | status_code=status.HTTP_201_CREATED, 35 | ) 36 | @limiter.limit(settings.API_RATE_LIMIT_REGISTER) 37 | async def register( 38 | request: Request, 39 | user_data: UserCreate, 40 | db: Session = Depends(get_db), 41 | ) -> UserResponse: 42 | """ 43 | Register a new user account 44 | """ 45 | return AuthService.register_user(db, user_data) 46 | 47 | 48 | @router.post( 49 | "/login", 50 | response_model=TokenResponse, 51 | status_code=status.HTTP_200_OK, 52 | ) 53 | @limiter.limit(settings.API_RATE_LIMIT_LOGIN) 54 | async def login( 55 | request: Request, 56 | login_data: UserLogin, 57 | db: Session = Depends(get_db), 58 | ) -> TokenResponse: 59 | """ 60 | Authenticate user and receive JWT token 61 | """ 62 | return AuthService.login_user(db, login_data) 63 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/Input.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // Input.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { type InputHTMLAttributes, forwardRef } from 'react'; 7 | import './Input.css'; 8 | 9 | interface InputProps extends InputHTMLAttributes { 10 | label: string; 11 | error?: string | undefined; 12 | } 13 | 14 | export const Input = forwardRef( 15 | ({ label, error, id, ...props }, ref) => { 16 | const inputId = 17 | id ?? `input-${label.toLowerCase().replace(/\s+/g, '-')}`; 18 | const errorId = `${inputId}-error`; 19 | 20 | return ( 21 |
22 | 28 | 38 | {error !== null && error !== undefined ? ( 39 | 46 | ) : null} 47 |
48 | ); 49 | }, 50 | ); 51 | 52 | Input.displayName = 'Input'; 53 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/schemas/test_result_schemas.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | TestResult model API validation and serialization 4 | """ 5 | 6 | from typing import Any 7 | from datetime import datetime 8 | from pydantic import ( 9 | BaseModel, 10 | ConfigDict, 11 | Field, 12 | ) 13 | 14 | from core.enums import ( 15 | ScanStatus, 16 | Severity, 17 | TestType, 18 | ) 19 | 20 | 21 | class TestResultCreate(BaseModel): 22 | """ 23 | Schema for creating a new test result (used by scanners) 24 | """ 25 | 26 | test_name: TestType 27 | status: ScanStatus 28 | severity: Severity 29 | details: str 30 | evidence_json: dict[str, Any] = Field(default_factory = dict) 31 | recommendations_json: list[str] = Field(default_factory = list) 32 | 33 | 34 | class TestResultResponse(BaseModel): 35 | """ 36 | Schema for individual test result in API responses 37 | """ 38 | 39 | model_config = ConfigDict(from_attributes = True) 40 | 41 | id: int 42 | scan_id: int 43 | test_name: TestType 44 | status: ScanStatus 45 | severity: Severity 46 | details: str 47 | evidence_json: dict[str, Any] 48 | recommendations_json: list[str] 49 | created_at: datetime 50 | 51 | @property 52 | def is_vulnerable(self) -> bool: 53 | """ 54 | Check if result indicates a vulnerability 55 | """ 56 | return self.status == ScanStatus.VULNERABLE 57 | 58 | @property 59 | def is_high_severity(self) -> bool: 60 | """ 61 | Check if vulnerability is high severity 62 | """ 63 | return self.severity == Severity.HIGH 64 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/stores/auth.store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Authentication state store 3 | * Manages current user and authentication status 4 | */ 5 | 6 | import { atom, computed } from "nanostores" 7 | import { persistentAtom } from "@nanostores/persistent" 8 | import type { User, Session } from "../types" 9 | 10 | export const $currentUser = atom(null) 11 | 12 | const $userIdRaw = persistentAtom("chat:user_id", "", { 13 | encode: (value: string) => value, 14 | decode: (value: string) => value, 15 | }) 16 | 17 | export const $userId = computed($userIdRaw, (id) => id !== "" ? id : null) 18 | 19 | export const $isAuthenticated = computed($userId, (id) => id !== null) 20 | 21 | export const $session = atom(null) 22 | 23 | export function setCurrentUser(user: User | null): void { 24 | $currentUser.set(user) 25 | $userIdRaw.set(user?.id ?? "") 26 | 27 | if (user !== null) { 28 | $session.set({ 29 | userId: user.id, 30 | username: user.username, 31 | displayName: user.display_name, 32 | isActive: user.is_active, 33 | authenticatedAt: new Date().toISOString(), 34 | }) 35 | } else { 36 | $session.set(null) 37 | } 38 | } 39 | 40 | export function logout(): void { 41 | $currentUser.set(null) 42 | $userIdRaw.set("") 43 | $session.set(null) 44 | } 45 | 46 | export function updateUserDisplayName(displayName: string): void { 47 | const user = $currentUser.get() 48 | if (user !== null) { 49 | $currentUser.set({ ...user, display_name: displayName }) 50 | 51 | const session = $session.get() 52 | if (session !== null) { 53 | $session.set({ ...session, displayName }) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/config-advanced.yaml: -------------------------------------------------------------------------------- 1 | # Ᾰenebris Advanced Configuration Example 2 | # This demonstrates multiple upstreams, load balancing, and routing 3 | 4 | version: 1 5 | 6 | # Multiple listen ports with TLS 7 | listen: 8 | - port: 80 9 | - port: 443 10 | tls: 11 | cert: /etc/aenebris/tls/cert.pem 12 | key: /etc/aenebris/tls/key.pem 13 | 14 | # Multiple backend upstreams 15 | upstreams: 16 | # API backend with load balancing 17 | - name: api-backend 18 | servers: 19 | - host: "10.0.1.10:8000" 20 | weight: 2 # Higher weight = more traffic 21 | - host: "10.0.1.11:8000" 22 | weight: 1 23 | health_check: 24 | path: /health 25 | interval: 10s 26 | 27 | # Web frontend backend 28 | - name: web-backend 29 | servers: 30 | - host: "10.0.2.10:3000" 31 | weight: 1 32 | health_check: 33 | path: / 34 | interval: 30s 35 | 36 | # Honeypot for suspicious traffic (future feature) 37 | - name: honeypot 38 | servers: 39 | - host: "127.0.0.1:9999" 40 | weight: 1 41 | 42 | # Virtual host routing 43 | routes: 44 | # API subdomain 45 | - host: "api.example.com" 46 | paths: 47 | - path: /v1 48 | upstream: api-backend 49 | rate_limit: 100/minute 50 | - path: /health 51 | upstream: api-backend 52 | 53 | # Main website 54 | - host: "www.example.com" 55 | paths: 56 | - path: / 57 | upstream: web-backend 58 | - path: /api 59 | upstream: api-backend 60 | rate_limit: 50/minute 61 | 62 | # Catch-all for example.com 63 | - host: "example.com" 64 | paths: 65 | - path: / 66 | upstream: web-backend 67 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/schemas/scan_schemas.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Scan model API validation and serialization 4 | """ 5 | 6 | from __future__ import annotations 7 | 8 | from pydantic import ( 9 | BaseModel, 10 | ConfigDict, 11 | Field, 12 | HttpUrl, 13 | ) 14 | from datetime import datetime 15 | 16 | from config import settings 17 | from core.enums import TestType 18 | from .test_result_schemas import TestResultResponse 19 | 20 | 21 | class ScanRequest(BaseModel): 22 | """ 23 | Schema for creating a new security scan 24 | """ 25 | 26 | target_url: HttpUrl = Field(max_length = settings.URL_MAX_LENGTH) 27 | auth_token: str | None = None 28 | tests_to_run: list[TestType] = Field(min_length = 1) 29 | max_requests: int = Field( 30 | default = settings.DEFAULT_MAX_REQUESTS, 31 | ge = 1, 32 | le = settings.SCANNER_MAX_CONCURRENT_REQUESTS, 33 | ) 34 | 35 | 36 | class ScanResponse(BaseModel): 37 | """ 38 | Schema for scan data in API responses 39 | """ 40 | 41 | model_config = ConfigDict(from_attributes = True) 42 | 43 | id: int 44 | user_id: int 45 | target_url: str 46 | scan_date: datetime 47 | created_at: datetime 48 | test_results: list[TestResultResponse] = [] 49 | 50 | @property 51 | def total_tests(self) -> int: 52 | """ 53 | Total number of tests run 54 | """ 55 | return len(self.test_results) 56 | 57 | @property 58 | def vulnerabilities_found(self) -> int: 59 | """ 60 | Number of vulnerabilities found 61 | """ 62 | return sum( 63 | 1 for r in self.test_results if r.status == "vulnerable" 64 | ) 65 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/UI/Badge.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 8-bit styled badge component 3 | */ 4 | 5 | import { Show } from "solid-js" 6 | import type { JSX } from "solid-js" 7 | import type { BadgeProps, Size, BadgeVariant } from "../../types" 8 | 9 | const SIZE_CLASSES: Record = { 10 | xs: "px-1 py-0.5 text-[6px]", 11 | sm: "px-1.5 py-0.5 text-[8px]", 12 | md: "px-2 py-1 text-[10px]", 13 | lg: "px-3 py-1 text-xs", 14 | xl: "px-4 py-1.5 text-sm", 15 | } 16 | 17 | const VARIANT_CLASSES: Record = { 18 | default: "bg-dark-gray text-white border-gray", 19 | primary: "bg-black text-orange border-orange", 20 | success: "bg-black text-success border-success", 21 | warning: "bg-black text-orange border-orange", 22 | error: "bg-black text-error border-error", 23 | } 24 | 25 | const DOT_COLORS: Record = { 26 | default: "bg-gray", 27 | primary: "bg-orange", 28 | success: "bg-success", 29 | warning: "bg-orange", 30 | error: "bg-error", 31 | } 32 | 33 | export function Badge(props: BadgeProps): JSX.Element { 34 | const variant = (): BadgeVariant => props.variant ?? "default" 35 | const size = (): Size => props.size ?? "md" 36 | const showDot = (): boolean => props.dot ?? false 37 | 38 | return ( 39 | 48 | 49 | 50 | 51 | {props.children} 52 | 53 | ) 54 | } 55 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/.env.example: -------------------------------------------------------------------------------- 1 | # Application 2 | ENV=development 3 | DEBUG=true 4 | APP_NAME=encrypted-p2p-chat 5 | SECRET_KEY=your-secret-key-here-change-in-production 6 | 7 | # Docker Host Ports (change these if you have conflicts) 8 | POSTGRES_HOST_PORT=5432 9 | SURREAL_HOST_PORT=8001 10 | REDIS_HOST_PORT=6379 11 | BACKEND_HOST_PORT=8000 12 | NGINX_HTTP_PORT=80 13 | NGINX_HTTPS_PORT=443 14 | 15 | # PostgreSQL (for auth data) 16 | POSTGRES_HOST=postgres 17 | POSTGRES_PORT=5432 18 | POSTGRES_DB=chat_auth 19 | POSTGRES_USER=chat_user 20 | POSTGRES_PASSWORD=change-this-password 21 | DATABASE_URL=postgresql+asyncpg://chat_user:change-this-password@postgres:5432/chat_auth 22 | DB_POOL_SIZE=20 23 | DB_MAX_OVERFLOW=40 24 | 25 | # SurrealDB (for real-time chat data) 26 | SURREAL_HOST=surrealdb 27 | SURREAL_PORT=8000 28 | SURREAL_USER=root 29 | SURREAL_PASSWORD=change-this-password 30 | SURREAL_NAMESPACE=chat 31 | SURREAL_DATABASE=production 32 | SURREAL_URL=ws://surrealdb:8000 33 | 34 | # Redis (for caching and rate limiting) 35 | REDIS_HOST=redis 36 | REDIS_PORT=6379 37 | REDIS_PASSWORD= 38 | REDIS_URL=redis://redis:6379 39 | 40 | # WebAuthn / Passkeys 41 | RP_ID=localhost 42 | RP_NAME=Encrypted P2P Chat 43 | RP_ORIGIN=http://localhost 44 | 45 | # Frontend (Vite requires VITE_ prefix) 46 | VITE_API_URL=http://localhost:8000 47 | VITE_WS_URL=ws://localhost:8000 48 | VITE_RP_ID=localhost 49 | 50 | # CORS 51 | CORS_ORIGINS=["http://localhost:3000","http://localhost:5173"] 52 | 53 | # WebSocket 54 | WS_HEARTBEAT_INTERVAL=30 55 | WS_MAX_CONNECTIONS_PER_USER=5 56 | 57 | # Encryption 58 | KEY_ROTATION_DAYS=90 59 | MAX_SKIPPED_MESSAGE_KEYS=1000 60 | 61 | # Rate Limiting 62 | RATE_LIMIT_MESSAGES_PER_MINUTE=60 63 | RATE_LIMIT_AUTH_ATTEMPTS=5 64 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/Chat/OnlineStatus.tsx: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // OnlineStatus.tsx 4 | // =================== 5 | import { Show } from "solid-js" 6 | import type { JSX } from "solid-js" 7 | import type { PresenceStatus } from "../../types" 8 | 9 | interface OnlineStatusProps { 10 | status: PresenceStatus 11 | size?: "sm" | "md" | "lg" 12 | showLabel?: boolean 13 | class?: string 14 | } 15 | 16 | const SIZE_MAP = { 17 | sm: "w-2 h-2", 18 | md: "w-3 h-3", 19 | lg: "w-4 h-4", 20 | } 21 | 22 | export function OnlineStatus(props: OnlineStatusProps): JSX.Element { 23 | const sizeClass = (): string => SIZE_MAP[props.size ?? "md"] 24 | 25 | const statusColor = (): string => { 26 | switch (props.status) { 27 | case "online": 28 | return "bg-success" 29 | case "away": 30 | return "bg-away" 31 | case "offline": 32 | return "bg-offline" 33 | default: 34 | return "bg-gray" 35 | } 36 | } 37 | 38 | const statusLabel = (): string => { 39 | switch (props.status) { 40 | case "online": 41 | return "ONLINE" 42 | case "away": 43 | return "AWAY" 44 | case "offline": 45 | return "OFFLINE" 46 | default: 47 | return "UNKNOWN" 48 | } 49 | } 50 | 51 | return ( 52 |
53 |
58 | 59 | 60 | {statusLabel()} 61 | 62 | 63 |
64 | ) 65 | } 66 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/scan/ScanForm.css: -------------------------------------------------------------------------------- 1 | .scan-form { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--spacing-lg); 5 | } 6 | 7 | .scan-form__fields { 8 | display: flex; 9 | flex-direction: column; 10 | gap: var(--spacing-md); 11 | } 12 | 13 | .scan-form__field { 14 | display: flex; 15 | flex-direction: column; 16 | gap: var(--spacing-xs); 17 | } 18 | 19 | .scan-form__label { 20 | font-size: var(--font-size-sm); 21 | font-weight: var(--font-weight-medium); 22 | color: var(--color-text-primary); 23 | display: flex; 24 | align-items: center; 25 | gap: var(--spacing-xs); 26 | } 27 | 28 | .scan-form__error { 29 | font-size: var(--font-size-sm); 30 | color: var(--color-danger); 31 | font-weight: var(--font-weight-normal); 32 | } 33 | 34 | .scan-form__checkboxes { 35 | display: grid; 36 | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); 37 | gap: var(--spacing-sm); 38 | } 39 | 40 | .scan-form__checkbox-label { 41 | display: flex; 42 | align-items: center; 43 | gap: var(--spacing-xs); 44 | padding: var(--spacing-sm); 45 | background: var(--glass-bg); 46 | border: 1px solid var(--glass-border); 47 | border-radius: var(--radius-md); 48 | cursor: pointer; 49 | transition: all var(--transition-base); 50 | font-size: var(--font-size-sm); 51 | color: var(--color-text-primary); 52 | } 53 | 54 | .scan-form__checkbox-label:hover { 55 | background: var(--glass-bg-hover); 56 | border-color: var(--glass-border-hover); 57 | } 58 | 59 | .scan-form__checkbox { 60 | width: 18px; 61 | height: 18px; 62 | cursor: pointer; 63 | accent-color: var(--color-accent-primary); 64 | } 65 | 66 | @media (width <= 768px) { 67 | .scan-form__checkboxes { 68 | grid-template-columns: 1fr; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributing Guidelines 2 | ======================= 3 | 4 | Thank you for your interest in contributing to this cybersecurity projects repository. 5 | 6 | How to Contribute 7 | ----------------- 8 | 9 | Adding Project Ideas 10 | ~~~~~~~~~~~~~~~~~~~~ 11 | 12 | If you have a cybersecurity project idea to add: 13 | 14 | 1. Fork the repository 15 | 2. Create a new markdown file in the appropriate SYNOPSES subfolder (beginner/intermediate/advanced) 16 | 3. Follow the existing format with a clear project description 17 | 4. Update the main README.md to include a link to your new project 18 | 5. Submit a pull request with a clear description of your addition 19 | 20 | Improving Existing Content 21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | 23 | To improve existing projects or documentation: 24 | 25 | 1. Fork the repository 26 | 2. Make your changes in a new branch 27 | 3. Ensure your changes are clear and well-documented 28 | 4. Submit a pull request explaining what you improved and why 29 | 30 | Building Full Projects 31 | ~~~~~~~~~~~~~~~~~~~~~~ 32 | 33 | If you want to contribute a fully built project: 34 | 35 | 1. Create the project in the ``/PROJECTS`` directory 36 | 2. Include complete source code and documentation 37 | 3. Add a detailed README in the project folder 38 | 4. Ensure the code follows security best practices and fully linted 39 | 5. Submit a pull request 40 | 41 | Guidelines 42 | ---------- 43 | 44 | * Keep descriptions concise and technical 45 | * Focus on practical, educational value 46 | * Ensure all projects are legal and ethical 47 | * Test any code before submitting 48 | * Follow existing formatting conventions 49 | * Write clear commit messages 50 | 51 | Questions 52 | --------- 53 | 54 | If you have questions about contributing, open an issue for discussion before starting significant work. 55 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/auth/AuthForm.css: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Auth form styles 4 | */ 5 | 6 | .auth-form { 7 | display: flex; 8 | flex-direction: column; 9 | gap: 24px; 10 | width: 100%; 11 | max-width: 420px; 12 | padding: 40px; 13 | background: rgb(255 255 255 / 5%); 14 | border: 1px solid rgb(255 255 255 / 10%); 15 | border-radius: 16px; 16 | backdrop-filter: blur(20px); 17 | box-shadow: 0 8px 32px 0 rgb(0 0 0 / 37%); 18 | } 19 | 20 | .auth-form__header { 21 | display: flex; 22 | flex-direction: column; 23 | gap: 8px; 24 | text-align: center; 25 | } 26 | 27 | .auth-form__title { 28 | font-size: 28px; 29 | font-weight: 700; 30 | color: #fff; 31 | margin: 0; 32 | letter-spacing: -0.02em; 33 | } 34 | 35 | .auth-form__subtitle { 36 | font-size: 14px; 37 | color: rgb(255 255 255 / 60%); 38 | margin: 0; 39 | } 40 | 41 | .auth-form__fields { 42 | display: flex; 43 | flex-direction: column; 44 | gap: 20px; 45 | } 46 | 47 | .auth-form__link { 48 | text-align: center; 49 | font-size: 14px; 50 | color: rgb(255 255 255 / 60%); 51 | margin: 0; 52 | } 53 | 54 | .auth-form__link-text { 55 | color: #3b82f6; 56 | font-weight: 600; 57 | text-decoration: none; 58 | transition: color 0.2s ease; 59 | } 60 | 61 | .auth-form__link-text:hover { 62 | color: #60a5fa; 63 | text-decoration: underline; 64 | } 65 | 66 | .auth-form__link-text:focus-visible { 67 | outline: 2px solid #60a5fa; 68 | outline-offset: 2px; 69 | border-radius: 2px; 70 | } 71 | 72 | .auth-form__error-message { 73 | padding: 12px 16px; 74 | background: rgb(220 38 38 / 10%); 75 | border: 1px solid rgb(220 38 38 / 30%); 76 | border-radius: 8px; 77 | color: #fca5a5; 78 | font-size: 14px; 79 | font-weight: 500; 80 | text-align: center; 81 | } 82 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/schemas/surreal.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Pydantic schemas for SurrealDB responses 4 | """ 5 | 6 | from datetime import datetime 7 | 8 | from pydantic import BaseModel 9 | 10 | from app.core.enums import PresenceStatus, RoomType 11 | 12 | 13 | class MessageResponse(BaseModel): 14 | """ 15 | Message response from SurrealDB 16 | """ 17 | id: str 18 | room_id: str | None = None 19 | sender_id: str 20 | recipient_id: str 21 | ciphertext: str 22 | nonce: str 23 | header: str 24 | sender_username: str 25 | created_at: datetime | None = None 26 | updated_at: datetime | None = None 27 | 28 | 29 | class RoomResponse(BaseModel): 30 | """ 31 | Room response from SurrealDB 32 | """ 33 | id: str 34 | name: str | None = None 35 | room_type: RoomType 36 | created_by: str 37 | created_at: datetime 38 | updated_at: datetime 39 | is_ephemeral: bool = False 40 | ttl_seconds: int | None = None 41 | 42 | 43 | class PresenceResponse(BaseModel): 44 | """ 45 | Presence response from SurrealDB 46 | """ 47 | id: str 48 | user_id: str 49 | room_id: str | None = None 50 | status: PresenceStatus 51 | last_seen: datetime 52 | updated_at: datetime 53 | 54 | 55 | class LiveQueryUpdate(BaseModel): 56 | """ 57 | Live query update notification from SurrealDB 58 | """ 59 | action: str 60 | result: MessageResponse | PresenceResponse | RoomResponse 61 | 62 | 63 | class LiveMessageUpdate(BaseModel): 64 | """ 65 | Live message update notification 66 | """ 67 | action: str 68 | result: MessageResponse 69 | 70 | 71 | class LivePresenceUpdate(BaseModel): 72 | """ 73 | Live presence update notification 74 | """ 75 | action: str 76 | result: PresenceResponse 77 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/.style.yapf: -------------------------------------------------------------------------------- 1 | [style] 2 | based_on_style = pep8 3 | column_limit = 74 4 | indent_width = 4 5 | continuation_indent_width = 4 6 | indent_closing_brackets = false 7 | dedent_closing_brackets = true 8 | indent_blank_lines = false 9 | spaces_before_comment = 2 10 | spaces_around_power_operator = false 11 | spaces_around_default_or_named_assign = true 12 | space_between_ending_comma_and_closing_bracket = false 13 | space_inside_brackets = false 14 | spaces_around_subscript_colon = true 15 | blank_line_before_nested_class_or_def = false 16 | blank_line_before_class_docstring = false 17 | blank_lines_around_top_level_definition = 2 18 | blank_lines_between_top_level_imports_and_variables = 2 19 | blank_line_before_module_docstring = false 20 | split_before_logical_operator = true 21 | split_before_first_argument = true 22 | split_before_named_assigns = true 23 | split_complex_comprehension = true 24 | split_before_expression_after_opening_paren = false 25 | split_before_closing_bracket = true 26 | split_all_comma_separated_values = true 27 | split_all_top_level_comma_separated_values = false 28 | coalesce_brackets = false 29 | each_dict_entry_on_separate_line = true 30 | allow_multiline_lambdas = false 31 | allow_multiline_dictionary_keys = false 32 | split_penalty_import_names = 0 33 | join_multiple_lines = false 34 | align_closing_bracket_with_visual_indent = true 35 | arithmetic_precedence_indication = false 36 | split_penalty_for_added_line_split = 275 37 | use_tabs = false 38 | split_before_dot = false 39 | split_arguments_when_comma_terminated = true 40 | i18n_function_call = ['_', 'N_', 'gettext', 'ngettext'] 41 | i18n_comment = ['# Translators:', '# i18n:'] 42 | split_penalty_comprehension = 80 43 | split_penalty_after_opening_bracket = 280 44 | split_penalty_before_if_expr = 0 45 | split_penalty_bitwise_operator = 290 46 | split_penalty_logical_operator = 0 47 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "printWidth": 77, 4 | "tabWidth": 2, 5 | "useTabs": false, 6 | "semi": true, 7 | "singleQuote": true, 8 | "quoteProps": "consistent", 9 | "jsxSingleQuote": false, 10 | "trailingComma": "all", 11 | "bracketSpacing": true, 12 | "bracketSameLine": false, 13 | "arrowParens": "always", 14 | "proseWrap": "always", 15 | "htmlWhitespaceSensitivity": "strict", 16 | "endOfLine": "lf", 17 | "embeddedLanguageFormatting": "auto", 18 | "singleAttributePerLine": true, 19 | "overrides": [ 20 | { 21 | "files": "*.tsx", 22 | "options": { 23 | "printWidth": 77, 24 | "jsxSingleQuote": false, 25 | "bracketSameLine": false 26 | } 27 | }, 28 | { 29 | "files": "*.ts", 30 | "options": { 31 | "printWidth": 77, 32 | "parser": "typescript" 33 | } 34 | }, 35 | { 36 | "files": ["*.json", "*.jsonc"], 37 | "options": { 38 | "printWidth": 80, 39 | "trailingComma": "none" 40 | } 41 | }, 42 | { 43 | "files": "*.scss", 44 | "options": { 45 | "singleQuote": false, 46 | "printWidth": 100 47 | } 48 | }, 49 | { 50 | "files": "*.md", 51 | "options": { 52 | "proseWrap": "always", 53 | "printWidth": 80 54 | } 55 | }, 56 | { 57 | "files": ["*.yml", "*.yaml"], 58 | "options": { 59 | "singleQuote": false, 60 | "bracketSpacing": true 61 | } 62 | }, 63 | { 64 | "files": ".prettierrc", 65 | "options": { 66 | "parser": "json" 67 | } 68 | }, 69 | { 70 | "files": "package.json", 71 | "options": { 72 | "printWidth": 1000 73 | } 74 | } 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/src/Aenebris/Middleware/Redirect.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | 3 | module Aenebris.Middleware.Redirect 4 | ( httpsRedirect 5 | , httpsRedirectWithPort 6 | ) where 7 | 8 | import qualified Data.ByteString.Char8 as BS 9 | import Data.Maybe (fromMaybe) 10 | import Network.HTTP.Types (status301, hLocation) 11 | import Network.Wai (Middleware, responseLBS, requestHeaderHost, rawPathInfo, rawQueryString, isSecure) 12 | 13 | -- | Redirect HTTP requests to HTTPS (assumes HTTPS is on port 443) 14 | httpsRedirect :: Middleware 15 | httpsRedirect = httpsRedirectWithPort Nothing 16 | 17 | -- | Redirect HTTP requests to HTTPS with optional custom port 18 | -- If port is Nothing, assumes 443 (standard HTTPS port, no port in URL) 19 | -- If port is Just n, includes :n in the redirect URL 20 | httpsRedirectWithPort :: Maybe Int -> Middleware 21 | httpsRedirectWithPort httpsPort app req respond 22 | | isSecure req = app req respond -- Already HTTPS, pass through 23 | | otherwise = do 24 | -- Get host from Host header 25 | let hostHeader = fromMaybe "localhost" $ requestHeaderHost req 26 | 27 | -- Build HTTPS URL with optional port 28 | host = case httpsPort of 29 | Nothing -> hostHeader -- Standard 443, don't include port 30 | Just 443 -> hostHeader -- Standard 443, don't include port 31 | Just port -> hostHeader <> ":" <> BS.pack (show port) 32 | 33 | -- Get path and query string (already encoded in rawPathInfo) 34 | path = rawPathInfo req 35 | query = rawQueryString req 36 | 37 | -- Build full redirect URL 38 | redirectUrl = "https://" <> host <> path <> query 39 | 40 | -- Send 301 permanent redirect 41 | respond $ responseLBS 42 | status301 43 | [(hLocation, redirectUrl)] 44 | "Redirecting to HTTPS" 45 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/.style.yapf: -------------------------------------------------------------------------------- 1 | [style] 2 | based_on_style = pep8 3 | column_limit = 82 4 | indent_width = 4 5 | continuation_indent_width = 4 6 | indent_closing_brackets = false 7 | dedent_closing_brackets = true 8 | indent_blank_lines = false 9 | spaces_before_comment = 2 10 | spaces_around_power_operator = false 11 | spaces_around_default_or_named_assign = true 12 | space_between_ending_comma_and_closing_bracket = false 13 | space_inside_brackets = false 14 | spaces_around_subscript_colon = true 15 | blank_line_before_nested_class_or_def = false 16 | blank_line_before_class_docstring = false 17 | blank_lines_around_top_level_definition = 2 18 | blank_lines_between_top_level_imports_and_variables = 2 19 | blank_line_before_module_docstring = false 20 | split_before_logical_operator = true 21 | split_before_first_argument = true 22 | split_before_named_assigns = true 23 | split_complex_comprehension = true 24 | split_before_expression_after_opening_paren = false 25 | split_before_closing_bracket = true 26 | split_all_comma_separated_values = true 27 | split_all_top_level_comma_separated_values = false 28 | coalesce_brackets = false 29 | each_dict_entry_on_separate_line = true 30 | allow_multiline_lambdas = false 31 | allow_multiline_dictionary_keys = false 32 | split_penalty_import_names = 0 33 | join_multiple_lines = false 34 | align_closing_bracket_with_visual_indent = true 35 | arithmetic_precedence_indication = false 36 | split_penalty_for_added_line_split = 275 37 | use_tabs = false 38 | split_before_dot = false 39 | split_arguments_when_comma_terminated = true 40 | i18n_function_call = ['_', 'N_', 'gettext', 'ngettext'] 41 | i18n_comment = ['# Translators:', '# i18n:'] 42 | split_penalty_comprehension = 80 43 | split_penalty_after_opening_bracket = 280 44 | split_penalty_before_if_expr = 0 45 | split_penalty_bitwise_operator = 290 46 | split_penalty_logical_operator = 0 47 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/core/dependencies.py: -------------------------------------------------------------------------------- 1 | """ 2 | FastAPI dependency injection functions. 3 | """ 4 | 5 | from fastapi import ( 6 | Depends, 7 | HTTPException, 8 | status, 9 | ) 10 | from fastapi.security import ( 11 | HTTPAuthorizationCredentials, 12 | HTTPBearer, 13 | ) 14 | from sqlalchemy.orm import Session 15 | from .security import decode_token 16 | from .database import get_db 17 | from repositories.user_repository import UserRepository 18 | from schemas.user_schemas import UserResponse 19 | 20 | 21 | security = HTTPBearer() 22 | 23 | 24 | async def get_current_user( 25 | credentials: HTTPAuthorizationCredentials = Depends(security), 26 | db: Session = Depends(get_db), 27 | ) -> UserResponse: 28 | """ 29 | FastAPI dependency to extract and verify the current authenticated user 30 | """ 31 | try: 32 | payload = decode_token(credentials.credentials) 33 | email: str | None = payload.get("sub") 34 | 35 | if email is None: 36 | raise HTTPException( 37 | status_code = status.HTTP_401_UNAUTHORIZED, 38 | detail = "Invalid authentication credentials", 39 | headers = {"WWW-Authenticate": "Bearer"}, 40 | ) 41 | 42 | user = UserRepository.get_by_email(db, email) 43 | 44 | if not user: 45 | raise HTTPException( 46 | status_code = status.HTTP_401_UNAUTHORIZED, 47 | detail = "User not found", 48 | headers = {"WWW-Authenticate": "Bearer"}, 49 | ) 50 | 51 | return UserResponse.model_validate(user) 52 | 53 | except ValueError: 54 | raise HTTPException( 55 | status_code = status.HTTP_401_UNAUTHORIZED, 56 | detail = "Invalid authentication credentials", 57 | headers = {"WWW-Authenticate": "Bearer"}, 58 | ) from None 59 | -------------------------------------------------------------------------------- /PROJECTS/dns-lookup/.style.yapf: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 | CarterPerez-dev 2 | [style] 3 | based_on_style = pep8 4 | column_limit = 70 5 | indent_width = 4 6 | continuation_indent_width = 4 7 | indent_closing_brackets = false 8 | dedent_closing_brackets = true 9 | indent_blank_lines = false 10 | spaces_before_comment = 2 11 | spaces_around_power_operator = false 12 | spaces_around_default_or_named_assign = true 13 | space_between_ending_comma_and_closing_bracket = false 14 | space_inside_brackets = false 15 | spaces_around_subscript_colon = true 16 | blank_line_before_nested_class_or_def = false 17 | blank_line_before_class_docstring = false 18 | blank_lines_around_top_level_definition = 2 19 | blank_lines_between_top_level_imports_and_variables = 2 20 | blank_line_before_module_docstring = false 21 | split_before_logical_operator = true 22 | split_before_first_argument = true 23 | split_before_named_assigns = true 24 | split_complex_comprehension = true 25 | split_before_expression_after_opening_paren = false 26 | split_before_closing_bracket = true 27 | split_all_comma_separated_values = true 28 | split_all_top_level_comma_separated_values = false 29 | coalesce_brackets = false 30 | each_dict_entry_on_separate_line = true 31 | allow_multiline_lambdas = false 32 | allow_multiline_dictionary_keys = false 33 | split_penalty_import_names = 0 34 | join_multiple_lines = false 35 | align_closing_bracket_with_visual_indent = true 36 | arithmetic_precedence_indication = false 37 | split_penalty_for_added_line_split = 275 38 | use_tabs = false 39 | split_before_dot = false 40 | split_arguments_when_comma_terminated = true 41 | i18n_function_call = ['_', 'N_', 'gettext', 'ngettext'] 42 | i18n_comment = ['# Translators:', '# i18n:'] 43 | split_penalty_comprehension = 80 44 | split_penalty_after_opening_bracket = 280 45 | split_penalty_before_if_expr = 0 46 | split_penalty_bitwise_operator = 290 47 | split_penalty_logical_operator = 0 48 | -------------------------------------------------------------------------------- /PROJECTS/keylogger/.style.yapf: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 | CarterPerez-dev 2 | [style] 3 | based_on_style = pep8 4 | column_limit = 70 5 | indent_width = 4 6 | continuation_indent_width = 4 7 | indent_closing_brackets = false 8 | dedent_closing_brackets = true 9 | indent_blank_lines = false 10 | spaces_before_comment = 2 11 | spaces_around_power_operator = false 12 | spaces_around_default_or_named_assign = true 13 | space_between_ending_comma_and_closing_bracket = false 14 | space_inside_brackets = false 15 | spaces_around_subscript_colon = true 16 | blank_line_before_nested_class_or_def = false 17 | blank_line_before_class_docstring = false 18 | blank_lines_around_top_level_definition = 2 19 | blank_lines_between_top_level_imports_and_variables = 2 20 | blank_line_before_module_docstring = false 21 | split_before_logical_operator = true 22 | split_before_first_argument = true 23 | split_before_named_assigns = true 24 | split_complex_comprehension = true 25 | split_before_expression_after_opening_paren = false 26 | split_before_closing_bracket = true 27 | split_all_comma_separated_values = true 28 | split_all_top_level_comma_separated_values = false 29 | coalesce_brackets = false 30 | each_dict_entry_on_separate_line = true 31 | allow_multiline_lambdas = false 32 | allow_multiline_dictionary_keys = false 33 | split_penalty_import_names = 0 34 | join_multiple_lines = false 35 | align_closing_bracket_with_visual_indent = true 36 | arithmetic_precedence_indication = false 37 | split_penalty_for_added_line_split = 275 38 | use_tabs = false 39 | split_before_dot = false 40 | split_arguments_when_comma_terminated = true 41 | i18n_function_call = ['_', 'N_', 'gettext', 'ngettext'] 42 | i18n_comment = ['# Translators:', '# i18n:'] 43 | split_penalty_comprehension = 80 44 | split_penalty_after_opening_bracket = 280 45 | split_penalty_before_if_expr = 0 46 | split_penalty_bitwise_operator = 290 47 | split_penalty_logical_operator = 0 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report a bug in existing code or documentation 3 | title: "[BUG] " 4 | labels: ["bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ## Bug Report 10 | Thanks for taking the time to report a bug. Please fill out the information below. 11 | 12 | - type: textarea 13 | id: description 14 | attributes: 15 | label: Description 16 | description: A clear description of the bug. 17 | placeholder: Describe what went wrong 18 | validations: 19 | required: true 20 | 21 | - type: textarea 22 | id: steps 23 | attributes: 24 | label: Steps to Reproduce 25 | description: How can we reproduce this issue? 26 | placeholder: | 27 | 1. 28 | 2. 29 | 3. 30 | validations: 31 | required: true 32 | 33 | - type: textarea 34 | id: expected 35 | attributes: 36 | label: Expected Behavior 37 | description: What you expected to happen. 38 | validations: 39 | required: true 40 | 41 | - type: textarea 42 | id: actual 43 | attributes: 44 | label: Actual Behavior 45 | description: What actually happened. 46 | validations: 47 | required: true 48 | 49 | - type: input 50 | id: os 51 | attributes: 52 | label: Operating System 53 | placeholder: e.g., Ubuntu 22.04, macOS 14, Windows 11 54 | 55 | - type: input 56 | id: version 57 | attributes: 58 | label: Python/Node Version 59 | placeholder: e.g., Python 3.11, Node 20 60 | 61 | - type: input 62 | id: project 63 | attributes: 64 | label: Project Affected 65 | placeholder: e.g., Port Scanner, API Security Tester 66 | 67 | - type: textarea 68 | id: context 69 | attributes: 70 | label: Additional Context 71 | description: Any other relevant information. 72 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/.style.yapf: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 | CarterPerez-dev 2 | [style] 3 | based_on_style = pep8 4 | column_limit = 70 5 | indent_width = 4 6 | continuation_indent_width = 4 7 | indent_closing_brackets = false 8 | dedent_closing_brackets = true 9 | indent_blank_lines = false 10 | spaces_before_comment = 2 11 | spaces_around_power_operator = false 12 | spaces_around_default_or_named_assign = true 13 | space_between_ending_comma_and_closing_bracket = false 14 | space_inside_brackets = false 15 | spaces_around_subscript_colon = true 16 | blank_line_before_nested_class_or_def = false 17 | blank_line_before_class_docstring = false 18 | blank_lines_around_top_level_definition = 2 19 | blank_lines_between_top_level_imports_and_variables = 2 20 | blank_line_before_module_docstring = false 21 | split_before_logical_operator = true 22 | split_before_first_argument = true 23 | split_before_named_assigns = true 24 | split_complex_comprehension = true 25 | split_before_expression_after_opening_paren = false 26 | split_before_closing_bracket = true 27 | split_all_comma_separated_values = true 28 | split_all_top_level_comma_separated_values = false 29 | coalesce_brackets = false 30 | each_dict_entry_on_separate_line = true 31 | allow_multiline_lambdas = false 32 | allow_multiline_dictionary_keys = false 33 | split_penalty_import_names = 0 34 | join_multiple_lines = false 35 | align_closing_bracket_with_visual_indent = true 36 | arithmetic_precedence_indication = false 37 | split_penalty_for_added_line_split = 275 38 | use_tabs = false 39 | split_before_dot = false 40 | split_arguments_when_comma_terminated = true 41 | i18n_function_call = ['_', 'N_', 'gettext', 'ngettext'] 42 | i18n_comment = ['# Translators:', '# i18n:'] 43 | split_penalty_comprehension = 80 44 | split_penalty_after_opening_bracket = 280 45 | split_penalty_before_if_expr = 0 46 | split_penalty_bitwise_operator = 290 47 | split_penalty_logical_operator = 0 48 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/test_backend.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Simple test backend for Aenebris proxy 4 | """ 5 | 6 | import json 7 | from http.server import ( 8 | HTTPServer, 9 | BaseHTTPRequestHandler, 10 | ) 11 | 12 | 13 | class TestHandler(BaseHTTPRequestHandler): 14 | def do_GET(self): 15 | # Health check endpoint 16 | if self.path == '/health': 17 | self.send_response(200) 18 | self.send_header('Content-Type', 'application/json') 19 | self.end_headers() 20 | response = {'status': 'healthy'} 21 | self.wfile.write(json.dumps(response).encode()) 22 | return 23 | 24 | # Normal request 25 | self.send_response(200) 26 | self.send_header('Content-Type', 'application/json') 27 | self.end_headers() 28 | 29 | response = { 30 | 'message': 'Hello from test backend!', 31 | 'path': self.path, 32 | 'method': 'GET' 33 | } 34 | self.wfile.write(json.dumps(response, indent = 2).encode()) 35 | 36 | def do_POST(self): 37 | content_length = int(self.headers.get('Content-Length', 0)) 38 | body = self.rfile.read(content_length) 39 | 40 | self.send_response(200) 41 | self.send_header('Content-Type', 'application/json') 42 | self.end_headers() 43 | 44 | response = { 45 | 'message': 'Received POST', 46 | 'path': self.path, 47 | 'method': 'POST', 48 | 'body_length': content_length 49 | } 50 | self.wfile.write(json.dumps(response, indent = 2).encode()) 51 | 52 | def log_message(self, format, *args): 53 | print(f"[BACKEND] {format % args}") 54 | 55 | 56 | if __name__ == '__main__': 57 | server = HTTPServer(('localhost', 8000), TestHandler) 58 | print('Test backend running on http://localhost:8000') 59 | server.serve_forever() 60 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/LoadingOverlay.css: -------------------------------------------------------------------------------- 1 | .loading-overlay { 2 | position: fixed; 3 | inset: 0; 4 | background: rgb(15 23 42 / 95%); 5 | backdrop-filter: blur(8px); 6 | display: flex; 7 | align-items: center; 8 | justify-content: center; 9 | z-index: var(--z-modal); 10 | animation: fade-in var(--transition-base); 11 | } 12 | 13 | @keyframes fade-in { 14 | from { 15 | opacity: 0; 16 | } 17 | 18 | to { 19 | opacity: 1; 20 | } 21 | } 22 | 23 | .loading-overlay__content { 24 | display: flex; 25 | flex-direction: column; 26 | align-items: center; 27 | gap: var(--spacing-lg); 28 | padding: var(--spacing-2xl); 29 | max-width: 500px; 30 | text-align: center; 31 | } 32 | 33 | .loading-overlay__spinner { 34 | width: 80px; 35 | height: 80px; 36 | } 37 | 38 | .spinner { 39 | width: 100%; 40 | height: 100%; 41 | border: 4px solid var(--glass-border); 42 | border-top-color: var(--color-accent-primary); 43 | border-radius: 50%; 44 | animation: spin 1s linear infinite; 45 | } 46 | 47 | @keyframes spin { 48 | to { 49 | transform: rotate(360deg); 50 | } 51 | } 52 | 53 | .loading-overlay__title { 54 | font-size: var(--font-size-2xl); 55 | font-weight: var(--font-weight-bold); 56 | color: var(--color-text-primary); 57 | margin: 0; 58 | } 59 | 60 | .loading-overlay__subtitle { 61 | font-size: var(--font-size-lg); 62 | color: var(--color-text-secondary); 63 | margin: 0; 64 | } 65 | 66 | .loading-overlay__tests { 67 | display: flex; 68 | flex-wrap: wrap; 69 | gap: var(--spacing-xs); 70 | justify-content: center; 71 | } 72 | 73 | .loading-overlay__test { 74 | padding: var(--spacing-xs) var(--spacing-md); 75 | background: var(--glass-bg); 76 | border: 1px solid var(--glass-border); 77 | border-radius: var(--radius-md); 78 | font-size: var(--font-size-sm); 79 | font-weight: var(--font-weight-medium); 80 | color: var(--color-text-primary); 81 | } 82 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/conf/nginx/dev.nginx: -------------------------------------------------------------------------------- 1 | # ⒸAngelaMos | 2025 2 | # Development Nginx Configuration 3 | # Features: 4 | # - Proxies to Vite dev server (with HMR/WebSocket support) 5 | # - Proxies /api to FastAPI backend 6 | # - No caching, no SSL 7 | 8 | events { 9 | worker_connections 1024; 10 | } 11 | 12 | http { 13 | # Include shared config and MIME types 14 | include /etc/nginx/http.conf; 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | # Disable access logs in dev (less noise) 19 | access_log off; 20 | error_log /var/log/nginx/error.log warn; 21 | 22 | server { 23 | listen 80; 24 | listen [::]:80; 25 | server_name localhost; 26 | 27 | # Client upload limits 28 | client_max_body_size 10M; 29 | client_body_buffer_size 128k; 30 | 31 | # Backend API 32 | location /api/ { 33 | proxy_pass http://backend/; 34 | proxy_http_version 1.1; 35 | proxy_set_header Upgrade $http_upgrade; 36 | proxy_set_header Connection 'upgrade'; 37 | proxy_set_header Host $host; 38 | proxy_set_header X-Real-IP $remote_addr; 39 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 40 | proxy_set_header X-Forwarded-Proto $scheme; 41 | proxy_cache_bypass $http_upgrade; 42 | } 43 | 44 | # Frontend 45 | location / { 46 | proxy_pass http://frontend; 47 | proxy_http_version 1.1; 48 | proxy_set_header Upgrade $http_upgrade; 49 | proxy_set_header Connection 'upgrade'; 50 | proxy_set_header Host $host; 51 | proxy_cache_bypass $http_upgrade; 52 | } 53 | 54 | location /health { 55 | access_log off; 56 | return 200 "healthy\n"; 57 | add_header Content-Type text/plain; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/User.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | User model for authentication stored in PostgreSQL 4 | """ 5 | 6 | from typing import TYPE_CHECKING 7 | from uuid import UUID, uuid4 8 | 9 | from sqlmodel import ( 10 | Field, 11 | Relationship, 12 | ) 13 | from app.config import ( 14 | DISPLAY_NAME_MAX_LENGTH, 15 | PREKEY_MAX_LENGTH, 16 | USERNAME_MAX_LENGTH, 17 | ) 18 | from app.models.Base import BaseDBModel 19 | 20 | if TYPE_CHECKING: 21 | from app.models.Credential import Credential 22 | 23 | 24 | class User(BaseDBModel, table = True): 25 | """ 26 | User account with WebAuthn passkey authentication 27 | """ 28 | __tablename__ = "users" 29 | 30 | id: UUID = Field( 31 | default_factory = uuid4, 32 | primary_key = True, 33 | nullable = False 34 | ) 35 | username: str = Field( 36 | unique = True, 37 | index = True, 38 | nullable = False, 39 | max_length = USERNAME_MAX_LENGTH 40 | ) 41 | display_name: str = Field( 42 | nullable = False, 43 | max_length = DISPLAY_NAME_MAX_LENGTH 44 | ) 45 | is_active: bool = Field(default = True, nullable = False) 46 | is_verified: bool = Field(default = False, nullable = False) 47 | 48 | credentials: list["Credential"] = Relationship(back_populates = "user") 49 | 50 | identity_key: str | None = Field( 51 | default = None, 52 | max_length = PREKEY_MAX_LENGTH 53 | ) 54 | signed_prekey: str | None = Field( 55 | default = None, 56 | max_length = PREKEY_MAX_LENGTH 57 | ) 58 | signed_prekey_signature: str | None = Field( 59 | default = None, 60 | max_length = PREKEY_MAX_LENGTH 61 | ) 62 | one_time_prekeys: str | None = Field(default = None) 63 | 64 | def __repr__(self) -> str: 65 | """ 66 | String representation of User 67 | """ 68 | return f"" 69 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/Base.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Base SQLModel class with async PostgreSQL engine setup 4 | """ 5 | 6 | from datetime import UTC, datetime 7 | from collections.abc import AsyncGenerator 8 | 9 | from sqlalchemy import DateTime 10 | from sqlalchemy.ext.asyncio import ( 11 | AsyncSession, 12 | create_async_engine, 13 | ) 14 | from sqlmodel import Field, SQLModel 15 | from sqlalchemy.orm import sessionmaker 16 | 17 | from app.config import settings 18 | 19 | 20 | class BaseDBModel(SQLModel): 21 | """ 22 | Base model with common timestamp fields 23 | """ 24 | created_at: datetime = Field( 25 | default_factory = lambda: datetime.now(UTC), 26 | nullable = False, 27 | sa_type = DateTime(timezone = True), 28 | ) 29 | updated_at: datetime = Field( 30 | default_factory = lambda: datetime.now(UTC), 31 | nullable = False, 32 | sa_type = DateTime(timezone = True), 33 | sa_column_kwargs = {"onupdate": lambda: datetime.now(UTC)}, 34 | ) 35 | 36 | 37 | # Create async engine for PostgreSQL 38 | engine = create_async_engine( 39 | str(settings.DATABASE_URL), 40 | echo = settings.DEBUG, 41 | pool_size = settings.DB_POOL_SIZE, 42 | max_overflow = settings.DB_MAX_OVERFLOW, 43 | pool_pre_ping = True, 44 | ) 45 | 46 | # Create async session factory 47 | async_session_maker = sessionmaker( # type: ignore[call-overload] 48 | bind = engine, 49 | class_ = AsyncSession, 50 | expire_on_commit = False, 51 | ) 52 | 53 | 54 | async def get_session() -> AsyncGenerator[AsyncSession]: 55 | """ 56 | Dependency for getting database sessions 57 | """ 58 | async with async_session_maker() as session: 59 | yield session 60 | 61 | 62 | async def init_db() -> None: 63 | """ 64 | Initialize database tables 65 | """ 66 | async with engine.begin() as conn: 67 | await conn.run_sync(SQLModel.metadata.create_all) 68 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/types/auth.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // auth.ts 4 | // =================== 5 | export interface User { 6 | id: string 7 | username: string 8 | display_name: string 9 | is_active: boolean 10 | is_verified: boolean 11 | created_at: string 12 | } 13 | 14 | export interface Credential { 15 | id: string 16 | credential_id: string 17 | device_name: string | null 18 | last_used_at: string | null 19 | created_at: string 20 | backup_eligible: boolean 21 | backup_state: boolean 22 | } 23 | 24 | export interface RegistrationBeginRequest { 25 | username: string 26 | display_name: string 27 | } 28 | 29 | export interface RegistrationCompleteRequest { 30 | username: string 31 | credential: PublicKeyCredentialJSON 32 | device_name?: string 33 | } 34 | 35 | export interface AuthenticationBeginRequest { 36 | username?: string 37 | } 38 | 39 | export interface AuthenticationCompleteRequest { 40 | credential: PublicKeyCredentialJSON 41 | } 42 | 43 | export interface WebAuthnOptions { 44 | publicKey: PublicKeyCredentialCreationOptions | PublicKeyCredentialRequestOptions 45 | } 46 | 47 | export interface PublicKeyCredentialJSON { 48 | id: string 49 | rawId: string 50 | type: "public-key" 51 | response: { 52 | clientDataJSON: string 53 | attestationObject?: string 54 | authenticatorData?: string 55 | signature?: string 56 | userHandle?: string 57 | } 58 | authenticatorAttachment?: "platform" | "cross-platform" 59 | clientExtensionResults: Record 60 | } 61 | 62 | export interface Session { 63 | userId: string 64 | username: string 65 | displayName: string 66 | isActive: boolean 67 | authenticatedAt: string 68 | } 69 | 70 | export const USERNAME_MIN_LENGTH = 3 71 | export const USERNAME_MAX_LENGTH = 50 72 | export const DISPLAY_NAME_MIN_LENGTH = 1 73 | export const DISPLAY_NAME_MAX_LENGTH = 100 74 | export const DEVICE_NAME_MAX_LENGTH = 100 75 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile 2 | # ⒸAngelaMos | 2025 3 | # Alias commands to easily run commands (use this or package.json scripts) 4 | 5 | .PHONY: help dev dev-build dev-down dev-logs prod prod-build prod-down prod-logs clean clean-all 6 | 7 | help: 8 | @echo "API Security Scanner - Available Commands" 9 | @echo "==========================================" 10 | @echo "" 11 | @echo "Development:" 12 | @echo " make dev - Start development environment" 13 | @echo " make dev-build - Build and start development environment" 14 | @echo " make dev-down - Stop development environment" 15 | @echo " make dev-logs - View development logs (follow mode)" 16 | @echo "" 17 | @echo "Production:" 18 | @echo " make prod - Start production environment (detached)" 19 | @echo " make prod-build - Build and start production environment" 20 | @echo " make prod-down - Stop production environment" 21 | @echo " make prod-logs - View production logs (follow mode)" 22 | @echo "" 23 | @echo "Cleanup:" 24 | @echo " make clean - Stop all containers and remove volumes" 25 | @echo " make clean-all - Clean + remove all Docker images/cache" 26 | @echo "" 27 | 28 | dev: 29 | docker compose -f docker-compose.dev.yml up 30 | 31 | dev-build: 32 | docker compose -f docker-compose.dev.yml up --build 33 | 34 | dev-down: 35 | docker compose -f docker-compose.dev.yml down 36 | 37 | dev-logs: 38 | docker compose -f docker-compose.dev.yml logs -f 39 | 40 | prod: 41 | docker compose -f docker-compose.prod.yml up -d 42 | 43 | prod-build: 44 | docker compose -f docker-compose.prod.yml up --build -d 45 | 46 | prod-down: 47 | docker compose -f docker-compose.prod.yml down 48 | 49 | prod-logs: 50 | docker compose -f docker-compose.prod.yml logs -f 51 | 52 | clean: 53 | docker compose -f docker-compose.dev.yml down -v 54 | docker compose -f docker-compose.prod.yml down -v 55 | 56 | clean-all: clean 57 | docker system prune -af --volumes 58 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/Makefile: -------------------------------------------------------------------------------- 1 | # Ᾰenebris Makefile - Common development commands 2 | 3 | .PHONY: help build run logs stop restart clean test backend kill-all 4 | 5 | help: 6 | @echo "Ᾰenebris Development Commands:" 7 | @echo "" 8 | @echo " make build - Build the project" 9 | @echo " make run - Start Ᾰenebris proxy" 10 | @echo " make logs - Watch logs in real-time" 11 | @echo " make stop - Stop the proxy" 12 | @echo " make restart - Restart the proxy" 13 | @echo " make clean - Clean build artifacts" 14 | @echo "" 15 | @echo " make backend - Start test backend (port 8000)" 16 | @echo " make test - Run tests (when implemented)" 17 | @echo " make kill-all - Kill proxy + backend" 18 | @echo "" 19 | 20 | build: 21 | @echo "Building Ᾰenebris..." 22 | @stack build 23 | 24 | run: 25 | @echo "Starting Ᾰenebris on port 8081..." 26 | @nohup stack run examples/config.yaml > aenebris.log 2>&1 & 27 | @sleep 2 28 | @echo "Proxy started! PID: $$(pgrep -f 'aenebris examples' | head -1)" 29 | @echo "Run 'make logs' to watch output" 30 | 31 | logs: 32 | @echo "Watching Ᾰenebris logs (Ctrl+C to exit)..." 33 | @tail -f aenebris.log 34 | 35 | stop: 36 | @echo "Stopping Ᾰenebris..." 37 | @pkill -f 'aenebris examples' || echo "Proxy not running" 38 | 39 | restart: stop 40 | @sleep 1 41 | @make run 42 | 43 | clean: 44 | @echo "Cleaning build artifacts..." 45 | @stack clean 46 | @rm -f aenebris.log nohup.out 47 | 48 | backend: 49 | @echo "Starting test backend on port 8000..." 50 | @python3 examples/test_backend.py > backend.log 2>&1 & 51 | @sleep 1 52 | @echo "Backend started! PID: $$(pgrep -f test_backend | head -1)" 53 | 54 | # Run tests (placeholder for now) 55 | test: 56 | @echo "Running tests..." 57 | @stack test 58 | 59 | kill-all: 60 | @echo "Killing all processes..." 61 | @pkill -f 'aenebris examples' || echo "Proxy not running" 62 | @pkill -f test_backend || echo "Backend not running" 63 | @echo "All processes stopped" 64 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/lib/validation.ts: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // ©AngelaMos | 2025 3 | // Zod Validation Schemas 4 | // =========================== 5 | 6 | import { z } from 'zod'; 7 | 8 | export const loginSchema = z.object({ 9 | email: z 10 | .email('Invalid email format') 11 | .min(1, 'Email is required') 12 | .max(255, 'Email too long'), 13 | password: z.string().min(1, 'Password is required'), 14 | }); 15 | 16 | export const registerSchema = z 17 | .object({ 18 | email: z 19 | .email('Invalid email format') 20 | .min(1, 'Email is required') 21 | .max(255, 'Email too long'), 22 | password: z 23 | .string() 24 | .min(8, 'Password must be at least 8 characters') 25 | .max(100, 'Password must be less than 100 characters') 26 | .regex(/[A-Z]/, 'Password must contain at least one uppercase letter') 27 | .regex(/[a-z]/, 'Password must contain at least one lowercase letter') 28 | .regex(/[0-9]/, 'Password must contain at least one number'), 29 | confirmPassword: z.string().min(1, 'Please confirm your password'), 30 | }) 31 | .refine((data) => data.password === data.confirmPassword, { 32 | message: 'Passwords do not match', 33 | path: ['confirmPassword'], 34 | }); 35 | 36 | export const scanSchema = z.object({ 37 | targetUrl: z 38 | .url('Invalid URL format') 39 | .min(1, 'Target URL is required') 40 | .max(2048, 'URL too long'), 41 | authToken: z.string().max(1000, 'Token too long').optional(), 42 | testsToRun: z 43 | .array(z.enum(['rate_limit', 'auth', 'sqli', 'idor'])) 44 | .min(1, 'Select at least one test'), 45 | maxRequests: z 46 | .number() 47 | .int('Must be a whole number') 48 | .min(1, 'Must be at least 1') 49 | .max(50, 'Maximum 50 requests allowed'), 50 | }); 51 | 52 | export type LoginFormData = z.infer; 53 | export type RegisterFormData = z.infer; 54 | export type ScanFormData = z.infer; 55 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/schemas/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Pydantic schemas exports 4 | """ 5 | 6 | from app.schemas.auth import ( 7 | AuthenticationBeginRequest, 8 | AuthenticationCompleteRequest, 9 | AuthenticationOptionsResponse, 10 | RegistrationBeginRequest, 11 | RegistrationCompleteRequest, 12 | RegistrationOptionsResponse, 13 | UserResponse, 14 | VerifiedAuthentication, 15 | VerifiedRegistration, 16 | ) 17 | from app.schemas.surreal import ( 18 | LiveMessageUpdate, 19 | LivePresenceUpdate, 20 | LiveQueryUpdate, 21 | MessageResponse, 22 | PresenceResponse, 23 | RoomResponse, 24 | ) 25 | from app.schemas.websocket import ( 26 | BaseWSMessage, 27 | EncryptedMessageWS, 28 | ErrorMessageWS, 29 | PresenceUpdateWS, 30 | ReadReceiptWS, 31 | TypingIndicatorWS, 32 | WSConnectionRequest, 33 | WSHeartbeat, 34 | ) 35 | from app.schemas.common import HealthResponse, RootResponse 36 | from app.schemas.rooms import ( 37 | CreateRoomRequest, 38 | ParticipantResponse, 39 | RoomAPIResponse, 40 | RoomListResponse, 41 | ) 42 | 43 | 44 | __all__ = [ 45 | "MessageResponse", 46 | "RoomResponse", 47 | "PresenceResponse", 48 | "LiveQueryUpdate", 49 | "LiveMessageUpdate", 50 | "LivePresenceUpdate", 51 | "RegistrationOptionsResponse", 52 | "VerifiedRegistration", 53 | "AuthenticationOptionsResponse", 54 | "VerifiedAuthentication", 55 | "RegistrationBeginRequest", 56 | "RegistrationCompleteRequest", 57 | "AuthenticationBeginRequest", 58 | "AuthenticationCompleteRequest", 59 | "UserResponse", 60 | "BaseWSMessage", 61 | "EncryptedMessageWS", 62 | "TypingIndicatorWS", 63 | "PresenceUpdateWS", 64 | "ReadReceiptWS", 65 | "ErrorMessageWS", 66 | "WSConnectionRequest", 67 | "WSHeartbeat", 68 | "RootResponse", 69 | "HealthResponse", 70 | "CreateRoomRequest", 71 | "ParticipantResponse", 72 | "RoomAPIResponse", 73 | "RoomListResponse", 74 | ] 75 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/schemas/user_schemas.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | User model API validation and serialization 4 | """ 5 | 6 | from __future__ import annotations 7 | 8 | import re 9 | from datetime import datetime 10 | 11 | from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator 12 | from config import settings 13 | 14 | 15 | class UserCreate(BaseModel): 16 | """ 17 | Schema for user registration request. 18 | """ 19 | 20 | email: EmailStr 21 | password: str = Field( 22 | min_length = settings.PASSWORD_MIN_LENGTH, 23 | max_length = settings.PASSWORD_MAX_LENGTH, 24 | ) 25 | 26 | @field_validator("password") 27 | @classmethod 28 | def validate_password_strength(cls, v: str) -> str: 29 | """ 30 | Validate password meets security requirements 31 | """ 32 | if not re.search(r"[A-Z]", v): 33 | raise ValueError( 34 | "Password must contain at least one uppercase letter" 35 | ) 36 | if not re.search(r"[a-z]", v): 37 | raise ValueError( 38 | "Password must contain at least one lowercase letter" 39 | ) 40 | if not re.search(r"[0-9]", v): 41 | raise ValueError( 42 | "Password must contain at least one number" 43 | ) 44 | return v 45 | 46 | 47 | class UserLogin(BaseModel): 48 | """ 49 | Schema for user login request. 50 | """ 51 | 52 | email: EmailStr 53 | password: str 54 | 55 | 56 | class UserResponse(BaseModel): 57 | """ 58 | Schema for user data in API responses. 59 | Excludes sensitive fields like hashed_password. 60 | """ 61 | 62 | model_config = ConfigDict(from_attributes = True) 63 | 64 | id: int 65 | email: str 66 | is_active: bool 67 | created_at: datetime 68 | 69 | 70 | class TokenResponse(BaseModel): 71 | """ 72 | Schema for JWT token response. 73 | """ 74 | 75 | access_token: str 76 | token_type: str = "bearer" 77 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/core/security.py: -------------------------------------------------------------------------------- 1 | """ 2 | Security utilities for password hashing and JWT token management. 3 | """ 4 | 5 | from datetime import ( 6 | datetime, 7 | timedelta, 8 | ) 9 | import bcrypt 10 | from jose import JWTError, jwt 11 | 12 | from config import settings 13 | 14 | 15 | def hash_password(password: str) -> str: 16 | """ 17 | Hash a plain text password using bcrypt 18 | """ 19 | password_bytes = password.encode("utf-8") 20 | salt = bcrypt.gensalt() 21 | hashed = bcrypt.hashpw(password_bytes, salt) 22 | return hashed.decode("utf-8") 23 | 24 | 25 | def verify_password( 26 | plain_password: str, 27 | hashed_password: str 28 | ) -> bool: 29 | """ 30 | Verify a plain text password against a hashed password 31 | """ 32 | password_bytes = plain_password.encode("utf-8") 33 | hashed_bytes = hashed_password.encode("utf-8") 34 | return bcrypt.checkpw(password_bytes, hashed_bytes) 35 | 36 | 37 | def create_access_token( 38 | data: dict[str, 39 | str], 40 | expires_delta: timedelta | None = None 41 | ) -> str: 42 | """ 43 | Create a JWT access token 44 | """ 45 | to_encode = data.copy() 46 | 47 | if expires_delta: 48 | expire = datetime.utcnow() + expires_delta 49 | else: 50 | expire = datetime.utcnow() + timedelta( 51 | minutes = settings.ACCESS_TOKEN_EXPIRE_MINUTES 52 | ) 53 | 54 | to_encode.update({"exp": expire}) 55 | encoded_jwt = jwt.encode( 56 | to_encode, 57 | settings.SECRET_KEY, 58 | algorithm = settings.ALGORITHM 59 | ) 60 | return encoded_jwt 61 | 62 | 63 | def decode_token(token: str) -> dict[str, str]: 64 | """ 65 | Decode and verify a JWT token 66 | """ 67 | try: 68 | payload = jwt.decode( 69 | token, 70 | settings.SECRET_KEY, 71 | algorithms = [settings.ALGORITHM] 72 | ) 73 | return payload 74 | except JWTError as e: 75 | raise ValueError(f"Invalid token: {str(e)}") from e 76 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/Auth/AuthCard.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 8-bit styled auth card container 3 | */ 4 | 5 | import type { ParentProps, JSX } from "solid-js" 6 | import { Show } from "solid-js" 7 | 8 | interface AuthCardProps extends ParentProps { 9 | title: string 10 | subtitle?: string 11 | } 12 | 13 | export function AuthCard(props: AuthCardProps): JSX.Element { 14 | return ( 15 |
16 |
23 |
24 |
25 | 26 |

27 | {props.title} 28 |

29 |
30 | 31 | 32 |

33 | {props.subtitle} 34 |

35 |
36 |
37 | 38 | {props.children} 39 |
40 | 41 |
42 | 43 | END-TO-END ENCRYPTED 44 | 45 |
46 |
47 | ) 48 | } 49 | 50 | function LockIcon(): JSX.Element { 51 | return ( 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | ) 61 | } 62 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/generate-test-certs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Generate self-signed certificates for testing Ᾰenebris TLS 4 | 5 | set -e 6 | 7 | echo "Generating test certificates for Ᾰenebris..." 8 | 9 | # Create certs directory if it doesn't exist 10 | mkdir -p examples/certs 11 | 12 | # Generate single certificate for localhost 13 | echo "→ Generating single certificate for localhost..." 14 | openssl req -x509 -newkey rsa:2048 -nodes \ 15 | -keyout examples/certs/localhost.key \ 16 | -out examples/certs/localhost.crt \ 17 | -days 365 \ 18 | -subj "/CN=localhost/O=Aenebris Test/C=US" 19 | 20 | # Generate SNI certificate for api.localhost 21 | echo "→ Generating SNI certificate for api.localhost..." 22 | openssl req -x509 -newkey rsa:2048 -nodes \ 23 | -keyout examples/certs/api.localhost.key \ 24 | -out examples/certs/api.localhost.crt \ 25 | -days 365 \ 26 | -subj "/CN=api.localhost/O=Aenebris Test/C=US" 27 | 28 | # Generate SNI certificate for web.localhost 29 | echo "→ Generating SNI certificate for web.localhost..." 30 | openssl req -x509 -newkey rsa:2048 -nodes \ 31 | -keyout examples/certs/web.localhost.key \ 32 | -out examples/certs/web.localhost.crt \ 33 | -days 365 \ 34 | -subj "/CN=web.localhost/O=Aenebris Test/C=US" 35 | 36 | # Generate default SNI certificate 37 | echo "→ Generating default SNI certificate..." 38 | openssl req -x509 -newkey rsa:2048 -nodes \ 39 | -keyout examples/certs/default.key \ 40 | -out examples/certs/default.crt \ 41 | -days 365 \ 42 | -subj "/CN=default.localhost/O=Aenebris Test/C=US" 43 | 44 | echo "✓ All test certificates generated successfully!" 45 | echo "" 46 | echo "Files created:" 47 | echo " examples/certs/localhost.{crt,key} - Single cert for localhost" 48 | echo " examples/certs/api.localhost.{crt,key} - SNI cert for api.localhost" 49 | echo " examples/certs/web.localhost.{crt,key} - SNI cert for web.localhost" 50 | echo " examples/certs/default.{crt,key} - Default SNI cert" 51 | echo "" 52 | echo "These are self-signed certificates for testing only!" 53 | echo "Use curl -k or --insecure to test HTTPS endpoints." 54 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/factory.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | FastAPI application factory for main.py 4 | """ 5 | 6 | from fastapi import FastAPI 7 | from fastapi.middleware.cors import CORSMiddleware 8 | 9 | from slowapi import ( 10 | Limiter, 11 | _rate_limit_exceeded_handler, 12 | ) 13 | from slowapi.errors import RateLimitExceeded 14 | from slowapi.util import get_remote_address 15 | 16 | from config import settings 17 | from core.database import Base, engine 18 | from routes import auth_router, scans_router 19 | 20 | 21 | def create_app() -> FastAPI: 22 | """ 23 | Application factory function 24 | """ 25 | Base.metadata.create_all(bind=engine) 26 | 27 | app = FastAPI( 28 | title=settings.APP_NAME, 29 | version=settings.VERSION, 30 | openapi_version="3.1.0", 31 | docs_url="/docs", 32 | redoc_url="/redoc", 33 | openapi_url="/openapi.json", 34 | debug=settings.DEBUG, 35 | ) 36 | 37 | limiter = Limiter(key_func=get_remote_address) 38 | app.state.limiter = limiter 39 | app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) 40 | 41 | app.add_middleware( 42 | CORSMiddleware, 43 | allow_origins=settings.cors_origins_list, 44 | allow_credentials=True, 45 | allow_methods=["*"], 46 | allow_headers=["*"], 47 | ) 48 | 49 | _register_routes(app) 50 | 51 | return app 52 | 53 | 54 | def _register_routes(app: FastAPI) -> None: 55 | """ 56 | Register all application routes 57 | """ 58 | 59 | @app.get("/") 60 | def root() -> dict[str, str]: 61 | """ 62 | API root endpoint 63 | """ 64 | return { 65 | "app": settings.APP_NAME, 66 | "version": settings.VERSION, 67 | "status": "healthy", 68 | } 69 | 70 | @app.get("/health") 71 | def health_check() -> dict[str, str]: 72 | """ 73 | Health check endpoint 74 | """ 75 | return {"status": "healthy"} 76 | 77 | app.include_router(auth_router) 78 | app.include_router(scans_router) 79 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/types/chat.ts: -------------------------------------------------------------------------------- 1 | // =================== 2 | // © AngelaMos | 2025 3 | // chat.ts 4 | // =================== 5 | export type MessageStatus = "sending" | "sent" | "delivered" | "read" | "failed" 6 | 7 | export type PresenceStatus = "online" | "away" | "offline" 8 | 9 | export type RoomType = "direct" | "group" | "ephemeral" 10 | 11 | export interface Message { 12 | id: string 13 | room_id: string 14 | sender_id: string 15 | sender_username: string 16 | content: string 17 | status: MessageStatus 18 | is_encrypted: boolean 19 | encrypted_content?: string 20 | nonce?: string 21 | header?: string 22 | created_at: string 23 | updated_at: string 24 | delivered_at?: string 25 | read_at?: string 26 | } 27 | 28 | export interface Room { 29 | id: string 30 | type: RoomType 31 | name?: string 32 | participants: Participant[] 33 | last_message?: Message 34 | unread_count: number 35 | is_encrypted: boolean 36 | created_at: string 37 | updated_at: string 38 | } 39 | 40 | export interface Participant { 41 | user_id: string 42 | username: string 43 | display_name: string 44 | role: "owner" | "admin" | "member" 45 | joined_at: string 46 | } 47 | 48 | export interface Conversation { 49 | room: Room 50 | messages: Message[] 51 | typing_users: string[] 52 | has_more_messages: boolean 53 | oldest_message_id?: string 54 | } 55 | 56 | export interface TypingState { 57 | user_id: string 58 | username: string 59 | started_at: string 60 | } 61 | 62 | export interface UserPresence { 63 | user_id: string 64 | status: PresenceStatus 65 | last_seen: string 66 | } 67 | 68 | export interface ReadReceipt { 69 | message_id: string 70 | user_id: string 71 | read_at: string 72 | } 73 | 74 | export interface FileAttachment { 75 | id: string 76 | message_id: string 77 | filename: string 78 | mime_type: string 79 | size_bytes: number 80 | url: string 81 | thumbnail_url?: string 82 | is_encrypted: boolean 83 | } 84 | 85 | export const MESSAGE_MAX_LENGTH = 50000 86 | export const DEFAULT_MESSAGE_LIMIT = 50 87 | export const MAX_MESSAGE_LIMIT = 200 88 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/components/UI/Spinner.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 8-bit styled spinner component 3 | */ 4 | 5 | import type { JSX } from "solid-js" 6 | import type { SpinnerProps, Size } from "../../types" 7 | 8 | const SIZE_CLASSES: Record = { 9 | xs: "w-3 h-3", 10 | sm: "w-4 h-4", 11 | md: "w-6 h-6", 12 | lg: "w-8 h-8", 13 | xl: "w-12 h-12", 14 | } 15 | 16 | export function Spinner(props: SpinnerProps): JSX.Element { 17 | const size = (): Size => props.size ?? "md" 18 | 19 | return ( 20 |
29 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 | ) 46 | } 47 | 48 | export function LoadingOverlay(): JSX.Element { 49 | return ( 50 |
51 |
52 | 53 | 54 | LOADING... 55 | 56 |
57 |
58 | ) 59 | } 60 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/core/exceptions.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Custom application exceptions for clean error handling 4 | """ 5 | 6 | 7 | class AppException(Exception): 8 | """ 9 | Base application exception 10 | """ 11 | def __init__(self, message: str) -> None: 12 | """ 13 | Initialize exception with message 14 | """ 15 | self.message = message 16 | super().__init__(self.message) 17 | 18 | 19 | class UserExistsError(AppException): 20 | """ 21 | Raised when attempting to create a user that already exists 22 | """ 23 | 24 | 25 | class UserNotFoundError(AppException): 26 | """ 27 | Raised when user cannot be found 28 | """ 29 | 30 | 31 | class UserInactiveError(AppException): 32 | """ 33 | Raised when user account is inactive 34 | """ 35 | 36 | 37 | class CredentialNotFoundError(AppException): 38 | """ 39 | Raised when credential cannot be found 40 | """ 41 | 42 | 43 | class CredentialVerificationError(AppException): 44 | """ 45 | Raised when credential verification fails 46 | """ 47 | 48 | 49 | class ChallengeExpiredError(AppException): 50 | """ 51 | Raised when WebAuthn challenge has expired or not found 52 | """ 53 | 54 | 55 | class DatabaseError(AppException): 56 | """ 57 | Raised when database operation fails 58 | """ 59 | 60 | 61 | class AuthenticationError(AppException): 62 | """ 63 | Raised when authentication fails 64 | """ 65 | 66 | 67 | class InvalidDataError(AppException): 68 | """ 69 | Raised when input data is invalid 70 | """ 71 | 72 | 73 | class EncryptionError(AppException): 74 | """ 75 | Raised when message encryption fails 76 | """ 77 | 78 | 79 | class DecryptionError(AppException): 80 | """ 81 | Raised when message decryption fails 82 | """ 83 | 84 | 85 | class RatchetStateNotFoundError(AppException): 86 | """ 87 | Raised when ratchet state not found for conversation 88 | """ 89 | 90 | 91 | class KeyExchangeError(AppException): 92 | """ 93 | Raised when X3DH key exchange fails 94 | """ 95 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/stores/session.store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Session tokens store with persistence 3 | * Stores authentication tokens in localStorage 4 | */ 5 | 6 | import { persistentMap, persistentAtom } from "@nanostores/persistent" 7 | 8 | interface SessionTokens { 9 | accessToken: string 10 | refreshToken: string 11 | expiresAt: number 12 | } 13 | 14 | const DEFAULT_TOKENS: SessionTokens = { 15 | accessToken: "", 16 | refreshToken: "", 17 | expiresAt: 0, 18 | } 19 | 20 | export const $sessionTokens = persistentMap( 21 | "chat:session:", 22 | DEFAULT_TOKENS, 23 | { 24 | encode: JSON.stringify, 25 | decode: JSON.parse, 26 | } 27 | ) 28 | 29 | export const $lastActivity = persistentAtom( 30 | "chat:last_activity", 31 | "", 32 | { 33 | encode: String, 34 | decode: String, 35 | } 36 | ) 37 | 38 | export function setSessionTokens( 39 | accessToken: string, 40 | refreshToken: string, 41 | expiresInSeconds: number 42 | ): void { 43 | const expiresAt = Date.now() + expiresInSeconds * 1000 44 | $sessionTokens.set({ 45 | accessToken, 46 | refreshToken, 47 | expiresAt, 48 | }) 49 | updateLastActivity() 50 | } 51 | 52 | export function clearSessionTokens(): void { 53 | $sessionTokens.set(DEFAULT_TOKENS) 54 | } 55 | 56 | export function isSessionValid(): boolean { 57 | const tokens = $sessionTokens.get() 58 | if (tokens.accessToken === "") { 59 | return false 60 | } 61 | return tokens.expiresAt > Date.now() 62 | } 63 | 64 | export function getAccessToken(): string | null { 65 | if (!isSessionValid()) { 66 | return null 67 | } 68 | return $sessionTokens.get().accessToken 69 | } 70 | 71 | export function getRefreshToken(): string | null { 72 | const tokens = $sessionTokens.get() 73 | return tokens.refreshToken !== "" ? tokens.refreshToken : null 74 | } 75 | 76 | export function updateLastActivity(): void { 77 | $lastActivity.set(new Date().toISOString()) 78 | } 79 | 80 | export function getLastActivity(): Date | null { 81 | const activity = $lastActivity.get() 82 | return activity !== "" ? new Date(activity) : null 83 | } 84 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/app/models/RatchetState.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Double Ratchet state model for per conversation encryption state 4 | """ 5 | 6 | from typing import TYPE_CHECKING 7 | from uuid import UUID 8 | 9 | from sqlmodel import Field 10 | 11 | from app.config import RATCHET_STATE_MAX_LENGTH 12 | from app.models.Base import BaseDBModel 13 | 14 | if TYPE_CHECKING: 15 | pass 16 | 17 | 18 | class RatchetState(BaseDBModel, table = True): 19 | """ 20 | Double Ratchet algorithm state for a conversation between two users 21 | """ 22 | __tablename__ = "ratchet_states" 23 | 24 | id: int = Field(default = None, primary_key = True) 25 | 26 | user_id: UUID = Field( 27 | foreign_key = "users.id", 28 | nullable = False, 29 | index = True 30 | ) 31 | peer_user_id: UUID = Field( 32 | foreign_key = "users.id", 33 | nullable = False, 34 | index = True 35 | ) 36 | 37 | dh_private_key: str | None = Field( 38 | default = None, 39 | max_length = RATCHET_STATE_MAX_LENGTH 40 | ) 41 | dh_public_key: str | None = Field( 42 | default = None, 43 | max_length = RATCHET_STATE_MAX_LENGTH 44 | ) 45 | dh_peer_public_key: str | None = Field( 46 | default = None, 47 | max_length = RATCHET_STATE_MAX_LENGTH 48 | ) 49 | 50 | root_key: str = Field(nullable = False, max_length = RATCHET_STATE_MAX_LENGTH) 51 | sending_chain_key: str = Field( 52 | nullable = False, 53 | max_length = RATCHET_STATE_MAX_LENGTH 54 | ) 55 | receiving_chain_key: str = Field( 56 | nullable = False, 57 | max_length = RATCHET_STATE_MAX_LENGTH 58 | ) 59 | 60 | sending_message_number: int = Field(default = 0, nullable = False) 61 | receiving_message_number: int = Field(default = 0, nullable = False) 62 | previous_sending_chain_length: int = Field(default = 0, nullable = False) 63 | 64 | def __repr__(self) -> str: 65 | """ 66 | String representation of RatchetState 67 | """ 68 | return f"" 69 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/stores/presence.store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Presence store 3 | * Manages user online/offline status 4 | */ 5 | 6 | import { map } from "nanostores" 7 | import type { PresenceStatus, UserPresence } from "../types" 8 | 9 | export const $presenceByUser = map>({}) 10 | 11 | export function setUserPresence( 12 | userId: string, 13 | status: PresenceStatus, 14 | lastSeen: string 15 | ): void { 16 | $presenceByUser.setKey(userId, { 17 | user_id: userId, 18 | status, 19 | last_seen: lastSeen, 20 | }) 21 | } 22 | 23 | export function updateUserStatus(userId: string, status: PresenceStatus): void { 24 | const presence = $presenceByUser.get()[userId] 25 | if (presence !== undefined) { 26 | $presenceByUser.setKey(userId, { 27 | ...presence, 28 | status, 29 | last_seen: new Date().toISOString(), 30 | }) 31 | } else { 32 | setUserPresence(userId, status, new Date().toISOString()) 33 | } 34 | } 35 | 36 | export function getUserPresence(userId: string): UserPresence | null { 37 | return $presenceByUser.get()[userId] ?? null 38 | } 39 | 40 | export function getUserStatus(userId: string): PresenceStatus { 41 | return $presenceByUser.get()[userId]?.status ?? "offline" 42 | } 43 | 44 | export function isUserOnline(userId: string): boolean { 45 | const status = getUserStatus(userId) 46 | return status === "online" 47 | } 48 | 49 | export function getOnlineUserIds(): string[] { 50 | const presences = $presenceByUser.get() 51 | return Object.entries(presences) 52 | .filter(([_, p]) => p.status === "online") 53 | .map(([id]) => id) 54 | } 55 | 56 | export function setMultiplePresences(presences: UserPresence[]): void { 57 | const presenceMap = { ...$presenceByUser.get() } 58 | for (const presence of presences) { 59 | presenceMap[presence.user_id] = presence 60 | } 61 | $presenceByUser.set(presenceMap) 62 | } 63 | 64 | export function removeUserPresence(userId: string): void { 65 | const { [userId]: _, ...rest } = $presenceByUser.get() 66 | $presenceByUser.set(rest) 67 | } 68 | 69 | export function clearAllPresences(): void { 70 | $presenceByUser.set({}) 71 | } 72 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/pages/DashboardPage.tsx: -------------------------------------------------------------------------------- 1 | // =========================== 2 | // DashboardPage.tsx 3 | // ©AngelaMos | 2025 4 | // =========================== 5 | 6 | import { useNavigate } from 'react-router-dom'; 7 | import { NewScanForm } from '@/components/scan/NewScanForm'; 8 | import { ScansList } from '@/components/scan/ScansList'; 9 | import { Button } from '@/components/common/Button'; 10 | import { useAuthStore } from '@/store/authStore'; 11 | import './DashboardPage.css'; 12 | 13 | export const DashboardPage = (): React.ReactElement => { 14 | const navigate = useNavigate(); 15 | const clearAuth = useAuthStore((state) => state.clearAuth); 16 | const user = useAuthStore((state) => state.user); 17 | 18 | const handleLogout = (): void => { 19 | clearAuth(); 20 | void navigate('/login'); 21 | }; 22 | 23 | return ( 24 |
25 |
26 |
27 |
28 |
29 |

API Security Scanner

30 |

31 | Test your APIs for security vulnerabilities 32 |

33 |
34 |
35 | {user?.email} 36 | 42 |
43 |
44 |
45 | 46 |
47 |
48 |

New Scan

49 | 50 |
51 | 52 |
53 |

Recent Scans

54 | 55 |
56 |
57 |
58 |
59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/models/Base.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Base model class 4 | Common fields and methods for all models 5 | """ 6 | 7 | from typing import Any 8 | from sqlalchemy import ( 9 | Column, 10 | DateTime, 11 | Integer, 12 | ) 13 | from datetime import datetime, UTC 14 | from sqlalchemy.ext.declarative import declared_attr 15 | 16 | from core.database import Base 17 | 18 | 19 | class BaseModel(Base): 20 | """ 21 | Abstract base model with common fields and methods 22 | All models inherit from this class 23 | """ 24 | 25 | __abstract__ = True 26 | 27 | id = Column( 28 | Integer, 29 | primary_key = True, 30 | index = True, 31 | autoincrement = True 32 | ) 33 | created_at = Column( 34 | DateTime(timezone = True), 35 | default = lambda: datetime.now(UTC) 36 | ) 37 | updated_at = Column( 38 | DateTime(timezone = True), 39 | default = lambda: datetime.now(UTC), 40 | onupdate = lambda: datetime.now(UTC), 41 | ) 42 | 43 | @declared_attr 44 | def __tablename__(cls) -> str: 45 | """ 46 | Auto-generate table name from class name 47 | """ 48 | return cls.__name__.lower() 49 | 50 | def to_dict(self) -> dict[str, Any]: 51 | """ 52 | Convert model instance to dictionary 53 | 54 | Returns: 55 | dict: Dictionary representation of the model 56 | """ 57 | return { 58 | column.name: getattr(self, 59 | column.name) 60 | for column in self.__table__.columns 61 | } 62 | 63 | def update(self, **kwargs: Any) -> None: 64 | """ 65 | Update model fields from keyword arguments 66 | 67 | Args: 68 | **kwargs: Field names and values to update 69 | """ 70 | for key, value in kwargs.items(): 71 | if hasattr(self, key): 72 | setattr(self, key, value) 73 | self.updated_at = datetime.now(UTC) 74 | 75 | def __repr__(self) -> str: 76 | """ 77 | String representation of model 78 | """ 79 | return f"<{self.__class__.__name__}(id={self.id})>" 80 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/models/Scan.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Scan model for storing security scan metadata 4 | """ 5 | 6 | from datetime import ( 7 | UTC, 8 | datetime, 9 | ) 10 | from sqlalchemy import ( 11 | Column, 12 | DateTime, 13 | ForeignKey, 14 | Integer, 15 | String, 16 | ) 17 | from sqlalchemy.orm import relationship 18 | 19 | from config import settings 20 | from .Base import BaseModel 21 | 22 | 23 | class Scan(BaseModel): 24 | """ 25 | Stores metadata about scans performed on target URLs 26 | """ 27 | 28 | __tablename__ = "scans" 29 | 30 | user_id = Column( 31 | Integer, 32 | ForeignKey("users.id", 33 | ondelete = "CASCADE"), 34 | nullable = False, 35 | index = True, 36 | ) 37 | target_url = Column( 38 | String(settings.URL_MAX_LENGTH), 39 | nullable = False, 40 | ) 41 | scan_date = Column( 42 | DateTime(timezone = True), 43 | default = lambda: datetime.now(UTC), 44 | nullable = False, 45 | ) 46 | 47 | user = relationship("User", backref = "scans") 48 | test_results = relationship( 49 | "TestResult", 50 | back_populates = "scan", 51 | cascade = "all, delete-orphan", 52 | ) 53 | 54 | def __repr__(self) -> str: 55 | """ 56 | String representation of Scan 57 | """ 58 | return f"" 59 | 60 | @property 61 | def has_vulnerabilities(self) -> bool: 62 | """ 63 | Check if scan found any vulnerabilities 64 | 65 | Returns: 66 | bool: True if any test result is vulnerable 67 | """ 68 | return any( 69 | result.status == "vulnerable" 70 | for result in self.test_results 71 | ) 72 | 73 | @property 74 | def vulnerability_count(self) -> int: 75 | """ 76 | Count of vulnerabilities found in this scan 77 | 78 | Returns: 79 | int: Number of vulnerable test results 80 | """ 81 | return sum( 82 | 1 for result in self.test_results 83 | if result.status == "vulnerable" 84 | ) 85 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/components/common/Button.css: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Button component styles 4 | */ 5 | 6 | .button { 7 | position: relative; 8 | display: inline-flex; 9 | align-items: center; 10 | justify-content: center; 11 | border-radius: 8px; 12 | font-weight: 600; 13 | font-family: inherit; 14 | transition: all 0.2s ease; 15 | cursor: pointer; 16 | border: 1px solid transparent; 17 | white-space: nowrap; 18 | backdrop-filter: blur(10px); 19 | } 20 | 21 | .button:focus-visible { 22 | outline: 2px solid #60a5fa; 23 | outline-offset: 2px; 24 | } 25 | 26 | .button:disabled { 27 | opacity: 0.5; 28 | cursor: not-allowed; 29 | pointer-events: none; 30 | } 31 | 32 | .button--sm { 33 | padding: 8px 16px; 34 | font-size: 14px; 35 | line-height: 20px; 36 | } 37 | 38 | .button--md { 39 | padding: 12px 24px; 40 | font-size: 16px; 41 | line-height: 24px; 42 | } 43 | 44 | .button--lg { 45 | padding: 16px 32px; 46 | font-size: 18px; 47 | line-height: 28px; 48 | } 49 | 50 | .button--primary { 51 | background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); 52 | color: #fff; 53 | border-color: rgb(255 255 255 / 20%); 54 | box-shadow: 0 4px 6px -1px rgb(0 0 0 / 30%), 55 | 0 2px 4px -1px rgb(0 0 0 / 20%); 56 | } 57 | 58 | .button--primary:hover:not(:disabled) { 59 | background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%); 60 | transform: translateY(-1px); 61 | box-shadow: 0 10px 15px -3px rgb(0 0 0 / 30%), 62 | 0 4px 6px -2px rgb(0 0 0 / 20%); 63 | } 64 | 65 | .button--primary:active:not(:disabled) { 66 | transform: translateY(0); 67 | box-shadow: 0 2px 4px -1px rgb(0 0 0 / 20%); 68 | } 69 | 70 | .button--secondary { 71 | background: rgb(255 255 255 / 10%); 72 | color: #fff; 73 | border-color: rgb(255 255 255 / 20%); 74 | box-shadow: 0 4px 6px -1px rgb(0 0 0 / 20%); 75 | } 76 | 77 | .button--secondary:hover:not(:disabled) { 78 | background: rgb(255 255 255 / 15%); 79 | border-color: rgb(255 255 255 / 30%); 80 | transform: translateY(-1px); 81 | } 82 | 83 | .button--ghost { 84 | background: transparent; 85 | color: #fff; 86 | border-color: transparent; 87 | } 88 | 89 | .button--ghost:hover:not(:disabled) { 90 | background: rgb(255 255 255 / 10%); 91 | } 92 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/backend/alembic/env.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | Alembic environment configuration for SQLModel migrations 4 | """ 5 | 6 | from logging.config import fileConfig 7 | 8 | from sqlalchemy import engine_from_config, pool 9 | from sqlmodel import SQLModel 10 | 11 | from alembic import context 12 | from app.config import settings 13 | 14 | # Import all models so they're registered with SQLModel metadata 15 | from app.models.User import User # noqa: F401 16 | from app.models.Credential import Credential # noqa: F401 17 | from app.models.IdentityKey import IdentityKey # noqa: F401 18 | from app.models.SignedPrekey import SignedPrekey # noqa: F401 19 | from app.models.OneTimePrekey import OneTimePrekey # noqa: F401 20 | from app.models.RatchetState import RatchetState # noqa: F401 21 | from app.models.SkippedMessageKey import SkippedMessageKey # noqa: F401 22 | 23 | 24 | config = context.config 25 | 26 | if config.config_file_name is not None: 27 | fileConfig(config.config_file_name) 28 | 29 | target_metadata = SQLModel.metadata 30 | 31 | config.set_main_option("sqlalchemy.url", str(settings.DATABASE_URL)) 32 | 33 | 34 | def run_migrations_offline() -> None: 35 | """ 36 | Run migrations in offline mode 37 | """ 38 | url = config.get_main_option("sqlalchemy.url") 39 | context.configure( 40 | url = url, 41 | target_metadata = target_metadata, 42 | literal_binds = True, 43 | dialect_opts = {"paramstyle": "named"}, 44 | ) 45 | 46 | with context.begin_transaction(): 47 | context.run_migrations() 48 | 49 | 50 | def run_migrations_online() -> None: 51 | """ 52 | Run migrations in online mode 53 | """ 54 | connectable = engine_from_config( 55 | config.get_section(config.config_ini_section, {}), 56 | prefix = "sqlalchemy.", 57 | poolclass = pool.NullPool, 58 | ) 59 | 60 | with connectable.connect() as connection: 61 | context.configure( 62 | connection = connection, 63 | target_metadata = target_metadata 64 | ) 65 | 66 | with context.begin_transaction(): 67 | context.run_migrations() 68 | 69 | 70 | if context.is_offline_mode(): 71 | run_migrations_offline() 72 | else: 73 | run_migrations_online() 74 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/project_submission.yml: -------------------------------------------------------------------------------- 1 | name: Project Submission 2 | description: Submit a completed project with full source code 3 | title: "[PROJECT] " 4 | labels: ["project"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ## Project Submission 10 | Submit a fully built cybersecurity project to the repository. 11 | 12 | - type: input 13 | id: project-name 14 | attributes: 15 | label: Project Name 16 | description: The name of the project you're submitting. 17 | placeholder: e.g., Advanced Port Scanner 18 | validations: 19 | required: true 20 | 21 | - type: dropdown 22 | id: category 23 | attributes: 24 | label: Category 25 | options: 26 | - Beginner 27 | - Intermediate 28 | - Advanced 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | id: description 34 | attributes: 35 | label: Description 36 | description: Brief description of what the project does. 37 | placeholder: Explain what your project does and its key features 38 | validations: 39 | required: true 40 | 41 | - type: textarea 42 | id: technologies 43 | attributes: 44 | label: Technologies Used 45 | description: List the main technologies, libraries, and frameworks. 46 | placeholder: e.g., Python 3.11, Scapy, FastAPI, PostgreSQL 47 | validations: 48 | required: true 49 | 50 | - type: textarea 51 | id: testing 52 | attributes: 53 | label: Testing 54 | description: Describe how you tested the project. 55 | validations: 56 | required: true 57 | 58 | - type: checkboxes 59 | id: documentation 60 | attributes: 61 | label: Documentation Checklist 62 | description: Confirm that your project includes the following 63 | options: 64 | - label: README with setup instructions 65 | required: true 66 | - label: Code comments 67 | required: true 68 | - label: Usage examples 69 | required: true 70 | - label: Security disclaimers (if applicable) 71 | required: false 72 | 73 | - type: textarea 74 | id: notes 75 | attributes: 76 | label: Additional Notes 77 | description: Any other relevant information. 78 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/styles/variables.css: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Design Variables - Customize colors, spacing, and visual style here 4 | */ 5 | 6 | :root { 7 | /* Background Colors */ 8 | --color-bg-primary: #0f172a; 9 | --color-bg-secondary: #1e293b; 10 | --color-bg-tertiary: #334155; 11 | 12 | /* Text Colors */ 13 | --color-text-primary: #f8fafc; 14 | --color-text-secondary: #94a3b8; 15 | --color-text-tertiary: #64748b; 16 | 17 | /* Status Colors */ 18 | --color-success: #16a34a; 19 | --color-danger: #dc2626; 20 | --color-warning: #f59e0b; 21 | --color-info: #3b82f6; 22 | 23 | /* Severity Colors */ 24 | --color-severity-critical: #dc2626; 25 | --color-severity-high: #ea580c; 26 | --color-severity-medium: #f59e0b; 27 | --color-severity-low: #3b82f6; 28 | --color-severity-info: #6b7280; 29 | 30 | /* Accent Colors */ 31 | --color-accent-primary: #3b82f6; 32 | --color-accent-hover: #2563eb; 33 | 34 | /* Glass Morphism */ 35 | --glass-bg: rgb(255 255 255 / 5%); 36 | --glass-bg-hover: rgb(255 255 255 / 8%); 37 | --glass-border: rgb(255 255 255 / 10%); 38 | --glass-border-hover: rgb(255 255 255 / 15%); 39 | 40 | /* Spacing */ 41 | --spacing-xs: 0.5rem; 42 | --spacing-sm: 1rem; 43 | --spacing-md: 1.5rem; 44 | --spacing-lg: 2rem; 45 | --spacing-xl: 3rem; 46 | --spacing-2xl: 4rem; 47 | 48 | /* Border Radius */ 49 | --radius-sm: 6px; 50 | --radius-md: 8px; 51 | --radius-lg: 12px; 52 | --radius-xl: 16px; 53 | 54 | /* Shadows */ 55 | --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 5%); 56 | --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 10%); 57 | --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 10%); 58 | 59 | /* Transitions */ 60 | --transition-fast: 150ms ease; 61 | --transition-base: 200ms ease; 62 | --transition-slow: 300ms ease; 63 | 64 | /* Typography */ 65 | --font-size-xs: 0.75rem; 66 | --font-size-sm: 0.875rem; 67 | --font-size-base: 1rem; 68 | --font-size-lg: 1.125rem; 69 | --font-size-xl: 1.25rem; 70 | --font-size-2xl: 1.5rem; 71 | --font-size-3xl: 2rem; 72 | --font-size-4xl: 2.5rem; 73 | --font-weight-normal: 400; 74 | --font-weight-medium: 500; 75 | --font-weight-semibold: 600; 76 | --font-weight-bold: 700; 77 | 78 | /* Z-index */ 79 | --z-dropdown: 1000; 80 | --z-modal: 2000; 81 | --z-toast: 3000; 82 | } 83 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/lib/api.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ©AngelaMos | 2025 3 | * Axios instance with request/response interceptors 4 | */ 5 | 6 | import axios, { type AxiosError, type AxiosResponse } from 'axios'; 7 | import { API_BASE_URL, STORAGE_KEYS } from '@/config/constants'; 8 | 9 | /** 10 | * Axios Base Config 11 | */ 12 | const axiosInstance = axios.create({ 13 | baseURL: API_BASE_URL, 14 | timeout: 180000, 15 | headers: { 16 | 'Content-Type': 'application/json', 17 | }, 18 | }); 19 | 20 | /** 21 | * Request interceptor 22 | */ 23 | axiosInstance.interceptors.request.use( 24 | (config) => { 25 | const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN); 26 | if (token) { 27 | config.headers.Authorization = `Bearer ${token}`; 28 | } 29 | return config; 30 | }, 31 | (error: AxiosError) => { 32 | return Promise.reject(error); 33 | }, 34 | ); 35 | 36 | /** 37 | * Response interceptor 38 | */ 39 | axiosInstance.interceptors.response.use( 40 | (response: AxiosResponse) => { 41 | return response; 42 | }, 43 | (error: AxiosError) => { 44 | if (error.response?.status === 401) { 45 | const requestUrl = error.config?.url ?? ''; 46 | const isAuthEndpoint = 47 | requestUrl.includes('/auth/login') || 48 | requestUrl.includes('/auth/register'); 49 | 50 | if (!isAuthEndpoint) { 51 | localStorage.removeItem(STORAGE_KEYS.AUTH_TOKEN); 52 | localStorage.removeItem(STORAGE_KEYS.USER); 53 | window.location.href = '/login'; 54 | } 55 | } 56 | return Promise.reject(error); 57 | }, 58 | ); 59 | 60 | /** 61 | * API wrapper 62 | */ 63 | export const api = { 64 | get: async (url: string): Promise => { 65 | const response = await axiosInstance.get(url); 66 | return response.data; 67 | }, 68 | 69 | post: async (url: string, data?: unknown): Promise => { 70 | const response = await axiosInstance.post(url, data); 71 | return response.data; 72 | }, 73 | 74 | put: async (url: string, data?: unknown): Promise => { 75 | const response = await axiosInstance.put(url, data); 76 | return response.data; 77 | }, 78 | 79 | delete: async (url: string): Promise => { 80 | const response = await axiosInstance.delete(url); 81 | return response.data; 82 | }, 83 | }; 84 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/src/pages/DashboardPage.css: -------------------------------------------------------------------------------- 1 | .dashboard { 2 | min-height: 100vh; 3 | background: linear-gradient(135deg, var(--color-bg-primary) 0%, var(--color-bg-secondary) 100%); 4 | padding: var(--spacing-lg); 5 | } 6 | 7 | .dashboard__container { 8 | max-width: 1200px; 9 | margin: 0 auto; 10 | } 11 | 12 | .dashboard__header { 13 | margin-bottom: var(--spacing-xl); 14 | } 15 | 16 | .dashboard__header-content { 17 | display: flex; 18 | justify-content: space-between; 19 | align-items: center; 20 | gap: var(--spacing-lg); 21 | } 22 | 23 | .dashboard__header-text { 24 | flex: 1; 25 | } 26 | 27 | .dashboard__title { 28 | font-size: var(--font-size-4xl); 29 | font-weight: var(--font-weight-bold); 30 | color: var(--color-text-primary); 31 | margin: 0 0 var(--spacing-xs) 0; 32 | letter-spacing: -0.02em; 33 | } 34 | 35 | .dashboard__subtitle { 36 | font-size: var(--font-size-lg); 37 | color: var(--color-text-secondary); 38 | margin: 0; 39 | } 40 | 41 | .dashboard__header-actions { 42 | display: flex; 43 | align-items: center; 44 | gap: var(--spacing-md); 45 | } 46 | 47 | .dashboard__user-email { 48 | font-size: var(--font-size-sm); 49 | color: var(--color-text-secondary); 50 | font-weight: var(--font-weight-medium); 51 | } 52 | 53 | .dashboard__content { 54 | display: flex; 55 | flex-direction: column; 56 | gap: var(--spacing-lg); 57 | } 58 | 59 | .dashboard__section { 60 | background: var(--glass-bg); 61 | backdrop-filter: blur(10px); 62 | border: 1px solid var(--glass-border); 63 | border-radius: var(--radius-lg); 64 | padding: var(--spacing-lg); 65 | } 66 | 67 | .dashboard__section-title { 68 | font-size: var(--font-size-2xl); 69 | font-weight: var(--font-weight-semibold); 70 | color: var(--color-text-primary); 71 | margin: 0 0 var(--spacing-md) 0; 72 | letter-spacing: -0.01em; 73 | } 74 | 75 | @media (width <= 768px) { 76 | .dashboard { 77 | padding: var(--spacing-sm); 78 | } 79 | 80 | .dashboard__header-content { 81 | flex-direction: column; 82 | align-items: flex-start; 83 | } 84 | 85 | .dashboard__title { 86 | font-size: var(--font-size-3xl); 87 | } 88 | 89 | .dashboard__header-actions { 90 | width: 100%; 91 | justify-content: space-between; 92 | } 93 | 94 | .dashboard__section { 95 | padding: var(--spacing-md); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/examples/test_backend_multi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Multi-instance test backend for Aenebris proxy load balancing 4 | Accepts port number as command-line argument 5 | """ 6 | 7 | import json 8 | import sys 9 | from http.server import ( 10 | HTTPServer, 11 | BaseHTTPRequestHandler, 12 | ) 13 | 14 | 15 | class TestHandler(BaseHTTPRequestHandler): 16 | def do_GET(self): 17 | if self.path == '/health': 18 | self.send_response(200) 19 | self.send_header('Content-Type', 'application/json') 20 | self.end_headers() 21 | response = { 22 | 'status': 'healthy', 23 | 'port': self.server.server_port 24 | } 25 | self.wfile.write(json.dumps(response).encode()) 26 | return 27 | 28 | self.send_response(200) 29 | self.send_header('Content-Type', 'application/json') 30 | self.end_headers() 31 | 32 | response = { 33 | 'message': 34 | f'Hello from backend on port {self.server.server_port}!', 35 | 'port': self.server.server_port, 36 | 'path': self.path, 37 | 'method': 'GET' 38 | } 39 | self.wfile.write(json.dumps(response, indent = 2).encode()) 40 | 41 | def do_POST(self): 42 | content_length = int(self.headers.get('Content-Length', 0)) 43 | body = self.rfile.read(content_length) 44 | 45 | self.send_response(200) 46 | self.send_header('Content-Type', 'application/json') 47 | self.end_headers() 48 | 49 | response = { 50 | 'message': 'Received POST', 51 | 'port': self.server.server_port, 52 | 'path': self.path, 53 | 'method': 'POST', 54 | 'body_length': content_length 55 | } 56 | self.wfile.write(json.dumps(response, indent = 2).encode()) 57 | 58 | def log_message(self, format, *args): 59 | print(f"[BACKEND:{self.server.server_port}] {format % args}") 60 | 61 | 62 | if __name__ == '__main__': 63 | if len(sys.argv) < 2: 64 | print("Usage: test_backend_multi.py ") 65 | sys.exit(1) 66 | 67 | port = int(sys.argv[1]) 68 | server = HTTPServer(('localhost', port), TestHandler) 69 | print(f'Test backend running on http://localhost:{port}') 70 | server.serve_forever() 71 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/backend/models/TestResult.py: -------------------------------------------------------------------------------- 1 | """ 2 | ⒸAngelaMos | 2025 3 | TestResult model for storing individual security test results 4 | """ 5 | 6 | from sqlalchemy import ( 7 | Column, 8 | Enum, 9 | Integer, 10 | Text, 11 | ForeignKey, 12 | ) 13 | from sqlalchemy.orm import relationship 14 | from sqlalchemy.dialects.postgresql import JSON 15 | 16 | from core.enums import ( 17 | ScanStatus, 18 | Severity, 19 | TestType, 20 | ) 21 | from .Base import BaseModel 22 | 23 | 24 | class TestResult(BaseModel): 25 | """ 26 | Stores individual test results for each security scan 27 | """ 28 | 29 | __tablename__ = "test_results" 30 | 31 | scan_id = Column( 32 | Integer, 33 | ForeignKey("scans.id", 34 | ondelete = "CASCADE"), 35 | nullable = False, 36 | index = True, 37 | ) 38 | test_name = Column( 39 | Enum(TestType), 40 | nullable = False, 41 | index = True, 42 | ) 43 | status = Column( 44 | Enum(ScanStatus), 45 | nullable = False, 46 | index = True, 47 | ) 48 | severity = Column( 49 | Enum(Severity), 50 | nullable = False, 51 | index = True, 52 | ) 53 | details = Column(Text, nullable = False) 54 | evidence_json = Column(JSON, nullable = False, default = dict) 55 | recommendations_json = Column( 56 | JSON, 57 | nullable = False, 58 | default = list 59 | ) 60 | 61 | scan = relationship("Scan", back_populates = "test_results") 62 | 63 | def __repr__(self) -> str: 64 | """ 65 | String representation of TestResult 66 | """ 67 | return ( 68 | f"" 70 | ) 71 | 72 | @property 73 | def is_vulnerable(self) -> bool: 74 | """ 75 | Check if this test result indicates a vulnerability 76 | 77 | Returns: 78 | bool: True if status is vulnerable 79 | """ 80 | return self.status == ScanStatus.VULNERABLE 81 | 82 | @property 83 | def is_high_severity(self) -> bool: 84 | """ 85 | Check if this is a high severity vulnerability 86 | 87 | Returns: 88 | bool: True if severity is high 89 | """ 90 | return self.severity == Severity.HIGH 91 | -------------------------------------------------------------------------------- /PROJECTS/api-security-scanner/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api-security-scanner", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "vite build", 8 | "dev": "vite", 9 | "format": "prettier --write \"**/*.{ts,tsx,scss}\"", 10 | "format:check": "prettier --check \"**/*.{ts,tsx,scss}\"", 11 | "lint": "npm run lint:eslint && npm run lint:scss && npm run lint:types", 12 | "lint:eslint": "eslint . --ext .ts,.tsx --max-warnings 0", 13 | "lint:scss": "stylelint \"src/**/*.css\" --max-warnings 0", 14 | "lint:scss:fix": "stylelint \"src/**/*.css\" --fix", 15 | "lint:types": "tsc --project tsconfig.app.json --noEmit" 16 | }, 17 | "dependencies": { 18 | "@hookform/resolvers": "^5.2.1", 19 | "@radix-ui/react-collapsible": "^1.1.12", 20 | "@radix-ui/react-dialog": "^1.1.15", 21 | "@radix-ui/react-dropdown-menu": "^2.1.16", 22 | "@radix-ui/react-tabs": "^1.1.13", 23 | "@radix-ui/react-toast": "^1.2.15", 24 | "@radix-ui/react-tooltip": "^1.2.8", 25 | "@tanstack/react-query": "^5.85.3", 26 | "@tanstack/react-query-devtools": "^5.85.3", 27 | "axios": "^1.12.2", 28 | "clsx": "^2.1.1", 29 | "date-fns": "^4.1.0", 30 | "immer": "^10.1.1", 31 | "react": "^19.1.1", 32 | "react-dom": "^19.1.1", 33 | "react-hook-form": "^7.62.0", 34 | "react-icons": "^5.5.0", 35 | "react-markdown": "^10.1.0", 36 | "react-router-dom": "^7.8.1", 37 | "recharts": "^3.1.2", 38 | "socket.io-client": "^4.8.1", 39 | "sonner": "^2.0.7", 40 | "zod": "^4.0.17", 41 | "zustand": "^5.0.7" 42 | }, 43 | "devDependencies": { 44 | "@eslint/js": "^9.33.0", 45 | "@types/react": "^19.1.10", 46 | "@types/react-dom": "^19.1.7", 47 | "@vitejs/plugin-react": "^5.0.0", 48 | "eslint": "^9.33.0", 49 | "eslint-config-prettier": "^10.1.8", 50 | "eslint-plugin-jsx-a11y": "^6.10.2", 51 | "eslint-plugin-react": "^7.37.5", 52 | "eslint-plugin-react-hooks": "^5.2.0", 53 | "eslint-plugin-react-refresh": "^0.4.20", 54 | "globals": "^16.3.0", 55 | "husky": "^8.0.0", 56 | "prettier": "^3.6.2", 57 | "stylelint": "^16.25.0", 58 | "stylelint-config-prettier-scss": "^1.0.0", 59 | "stylelint-config-standard-scss": "^16.0.0", 60 | "typescript": "~5.8.3", 61 | "typescript-eslint": "^8.39.1", 62 | "vite": "^7.1.2", 63 | "vite-tsconfig-paths": "^5.1.4" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /PROJECTS/encrypted-p2p-chat/frontend/src/stores/rooms.store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Rooms/Conversations store 3 | * Manages chat rooms and active conversation state 4 | */ 5 | 6 | import { atom, computed, map } from "nanostores" 7 | import type { Room } from "../types" 8 | 9 | export const $rooms = map>({}) 10 | 11 | export const $activeRoomId = atom(null) 12 | 13 | export const $activeRoom = computed( 14 | [$rooms, $activeRoomId], 15 | (rooms, activeId) => (activeId ? rooms[activeId] ?? null : null) 16 | ) 17 | 18 | export const $roomList = computed($rooms, (rooms) => 19 | Object.values(rooms).sort((a, b) => { 20 | const aTime = a.last_message?.created_at ?? a.updated_at 21 | const bTime = b.last_message?.created_at ?? b.updated_at 22 | return new Date(bTime).getTime() - new Date(aTime).getTime() 23 | }) 24 | ) 25 | 26 | export const $totalUnreadCount = computed($rooms, (rooms) => 27 | Object.values(rooms).reduce((sum, room) => sum + room.unread_count, 0) 28 | ) 29 | 30 | export function setActiveRoom(roomId: string | null): void { 31 | $activeRoomId.set(roomId) 32 | } 33 | 34 | export function addRoom(room: Room): void { 35 | $rooms.setKey(room.id, room) 36 | } 37 | 38 | export function updateRoom(roomId: string, updates: Partial): void { 39 | const room = $rooms.get()[roomId] 40 | if (room !== undefined) { 41 | $rooms.setKey(roomId, { ...room, ...updates }) 42 | } 43 | } 44 | 45 | export function removeRoom(roomId: string): void { 46 | const { [roomId]: _, ...rest } = $rooms.get() 47 | $rooms.set(rest) 48 | 49 | if ($activeRoomId.get() === roomId) { 50 | $activeRoomId.set(null) 51 | } 52 | } 53 | 54 | export function setRooms(rooms: Room[]): void { 55 | const roomMap: Record = {} 56 | for (const room of rooms) { 57 | roomMap[room.id] = room 58 | } 59 | $rooms.set(roomMap) 60 | } 61 | 62 | export function clearUnreadCount(roomId: string): void { 63 | updateRoom(roomId, { unread_count: 0 }) 64 | } 65 | 66 | export function incrementUnreadCount(roomId: string): void { 67 | const room = $rooms.get()[roomId] 68 | if (room !== undefined) { 69 | updateRoom(roomId, { unread_count: room.unread_count + 1 }) 70 | } 71 | } 72 | 73 | export function getRoomById(roomId: string): Room | null { 74 | return $rooms.get()[roomId] ?? null 75 | } 76 | 77 | export function clearRooms(): void { 78 | $rooms.set({}) 79 | $activeRoomId.set(null) 80 | } 81 | -------------------------------------------------------------------------------- /PROJECTS/Aenebris/stack.yaml: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by 'stack init' 2 | # 3 | # Some commonly used options have been documented as comments in this file. 4 | # For advanced use and comprehensive documentation of the format, please see: 5 | # https://docs.haskellstack.org/en/stable/configure/yaml/ 6 | 7 | # A 'specific' Stackage snapshot or a compiler version. 8 | # A snapshot resolver dictates the compiler version and the set of packages 9 | # to be used for project dependencies. For example: 10 | # 11 | # snapshot: lts-23.0 12 | # snapshot: nightly-2024-12-13 13 | # snapshot: ghc-9.8.4 14 | # 15 | # The location of a snapshot can be provided as a file or url. Stack assumes 16 | # a snapshot provided as a file might change, whereas a url resource does not. 17 | # 18 | # snapshot: ./custom-snapshot.yaml 19 | # snapshot: https://example.com/snapshots/2024-01-01.yaml 20 | snapshot: 21 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/19.yaml 22 | 23 | # User packages to be built. 24 | # Various formats can be used as shown in the example below. 25 | # 26 | # packages: 27 | # - some-directory 28 | # - https://example.com/foo/bar/baz-0.0.2.tar.gz 29 | # subdirs: 30 | # - auto-update 31 | # - wai 32 | packages: 33 | - . 34 | # Dependency packages to be pulled from upstream that are not in the snapshot. 35 | # These entries can reference officially published versions as well as 36 | # forks / in-progress versions pinned to a git hash. For example: 37 | # 38 | # extra-deps: 39 | # - acme-missiles-0.3 40 | # - git: https://github.com/commercialhaskell/stack.git 41 | # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a 42 | # 43 | # extra-deps: [] 44 | 45 | # Override default flag values for project packages and extra-deps 46 | # flags: {} 47 | 48 | # Extra package databases containing global packages 49 | # extra-package-dbs: [] 50 | 51 | # Control whether we use the GHC we find on the path 52 | # system-ghc: true 53 | # 54 | # Require a specific version of Stack, using version ranges 55 | # require-stack-version: -any # Default 56 | # require-stack-version: ">=3.3" 57 | # 58 | # Override the architecture used by Stack, especially useful on Windows 59 | # arch: i386 60 | # arch: x86_64 61 | # 62 | # Extra directories used by Stack for building 63 | # extra-include-dirs: [/path/to/dir] 64 | # extra-lib-dirs: [/path/to/dir] 65 | # 66 | # Allow a newer minor version of GHC than the snapshot specifies 67 | # compiler-check: newer-minor 68 | --------------------------------------------------------------------------------