├── dashboard ├── src │ ├── lib │ │ ├── index.ts │ │ ├── components │ │ │ ├── utils │ │ │ │ ├── title.svelte │ │ │ │ ├── wordmark.svelte │ │ │ │ └── tooltip.svelte │ │ │ ├── cards │ │ │ │ ├── alert.svelte │ │ │ │ ├── connection.svelte │ │ │ │ └── approval.svelte │ │ │ ├── buttons │ │ │ │ ├── action.svelte │ │ │ │ └── basic.svelte │ │ │ ├── inputs │ │ │ │ └── field.svelte │ │ │ ├── modals │ │ │ │ └── basic.svelte │ │ │ └── navs │ │ │ │ ├── sidebar.svelte │ │ │ │ └── header.svelte │ │ ├── store.ts │ │ └── types.ts │ ├── app.d.ts │ ├── routes │ │ ├── connections │ │ │ └── [id] │ │ │ │ ├── +page.ts │ │ │ │ └── +page.svelte │ │ ├── +layout.svelte │ │ └── +page.svelte │ ├── app.html │ └── app.css ├── .npmrc ├── .dockerignore ├── .prettierignore ├── static │ └── imgs │ │ ├── favicon32.png │ │ └── favicon256.png ├── postcss.config.js ├── tailwind.config.js ├── vite.config.ts ├── svelte.config.js ├── tsconfig.json ├── Dockerfile ├── eslint.config.js └── package.json ├── clients ├── python │ ├── tests │ │ └── __init__.py │ ├── phantasmpy │ │ ├── __init__.py │ │ ├── stubs │ │ │ ├── __init__.py │ │ │ ├── receiver_pb2.py │ │ │ └── receiver_pb2_grpc.py │ │ ├── types.py │ │ └── client.py │ ├── pyproject.toml │ ├── README.md │ └── poetry.lock ├── .note └── LICENSE ├── docs ├── CNAME ├── assets │ └── favicon64.png ├── styles.css ├── docs │ ├── reference.md │ └── configuration.md └── index.md ├── requirements.txt ├── .env.example ├── src ├── protos.rs ├── types.rs ├── services │ ├── receiver.rs │ └── mod.rs └── main.rs ├── .dockerignore ├── .rustfmt.toml ├── .prettierrc.yml ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── question.md │ ├── feature_request.md │ └── bug_report.md ├── workflows │ ├── dashboard-ci.yml │ ├── sdk-python-cd.yml │ ├── .note │ ├── server-ci.yml │ ├── dashboard-cd.yml │ ├── docs-cd.yml │ └── server-cd.yml ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── CHANGELOG.md ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md ├── Dockerfile ├── Cargo.toml ├── Makefile ├── protos └── receiver.proto ├── mkdocs.yml ├── README.md └── LICENSE /dashboard/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /clients/python/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.phantasmlabs.com 2 | -------------------------------------------------------------------------------- /dashboard/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material==9.5.43 2 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | PHANTASM_SECRET=xxx 2 | PHANTASM_AUTO_APPROVE=xxx 3 | -------------------------------------------------------------------------------- /dashboard/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .svelte-kit 4 | .prettierignore 5 | -------------------------------------------------------------------------------- /dashboard/src/app.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace App {} 3 | } 4 | 5 | export {} 6 | -------------------------------------------------------------------------------- /docs/assets/favicon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phantasmlabs/phantasm/HEAD/docs/assets/favicon64.png -------------------------------------------------------------------------------- /src/protos.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::all)] 2 | #![allow(unused_qualifications)] 3 | tonic::include_proto!("receiver"); 4 | -------------------------------------------------------------------------------- /dashboard/.prettierignore: -------------------------------------------------------------------------------- 1 | .svelte-kit/ 2 | build/ 3 | node_modules/ 4 | package-lock.json 5 | pnpm-lock.yaml 6 | yarn.lock 7 | -------------------------------------------------------------------------------- /dashboard/static/imgs/favicon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phantasmlabs/phantasm/HEAD/dashboard/static/imgs/favicon32.png -------------------------------------------------------------------------------- /dashboard/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /dashboard/static/imgs/favicon256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phantasmlabs/phantasm/HEAD/dashboard/static/imgs/favicon256.png -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Project 2 | clients 3 | dashboard 4 | target 5 | 6 | # Other 7 | .git 8 | .github 9 | .gitignore 10 | .ds_store 11 | -------------------------------------------------------------------------------- /docs/styles.css: -------------------------------------------------------------------------------- 1 | h1, 2 | h2, 3 | h3 { 4 | font-weight: bold !important; 5 | } 6 | 7 | img { 8 | border-radius: 16px; 9 | } 10 | -------------------------------------------------------------------------------- /clients/python/phantasmpy/__init__.py: -------------------------------------------------------------------------------- 1 | from phantasmpy.client import Phantasm 2 | from phantasmpy.types import HeartbeatResponse, GetApprovalResponse 3 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | match_block_trailing_comma = true 2 | max_width = 80 3 | merge_derives = false 4 | use_small_heuristics = "Max" 5 | use_try_shorthand = true 6 | -------------------------------------------------------------------------------- /dashboard/tailwind.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | content: ["./src/**/*.{html,js,svelte,ts}"], 3 | theme: { 4 | extend: {} 5 | }, 6 | plugins: [] 7 | } 8 | -------------------------------------------------------------------------------- /dashboard/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from "@sveltejs/kit/vite" 2 | import { defineConfig } from "vite" 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }) 7 | -------------------------------------------------------------------------------- /dashboard/src/routes/connections/[id]/+page.ts: -------------------------------------------------------------------------------- 1 | type Params = { 2 | id: string 3 | } 4 | 5 | export function load({ params }: { params: Params }) { 6 | return { 7 | id: params.id 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/utils/title.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | {full} 8 | 9 | -------------------------------------------------------------------------------- /dashboard/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from "@sveltejs/adapter-node" 2 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte" 3 | 4 | const config = { 5 | preprocess: vitePreprocess(), 6 | kit: { adapter: adapter() } 7 | } 8 | 9 | export default config 10 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | bracketSpacing: true 2 | singleQuote: false 3 | trailingComma: "none" 4 | semi: false 5 | tabWidth: 2 6 | printWidth: 80 7 | proseWrap: "always" 8 | 9 | plugins: 10 | - prettier-plugin-svelte 11 | 12 | overrides: 13 | - files: "*.svelte" 14 | options: 15 | parser: svelte 16 | -------------------------------------------------------------------------------- /dashboard/src/lib/store.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store" 2 | import type { Connection, Alert, Approver } from "./types.ts" 3 | 4 | export const approver = writable(undefined) 5 | export const connections = writable([]) 6 | export const alerts = writable([]) 7 | -------------------------------------------------------------------------------- /clients/python/phantasmpy/stubs/__init__.py: -------------------------------------------------------------------------------- 1 | # If you encounter this error: 2 | # File ".../receiver_pb2_grpc.py", line 7, in 3 | # import receiver_pb2 as receiver__pb2 4 | # ModuleNotFoundError: No module named 'receiver_pb2' 5 | # 6 | # You need to change the import statement in receiver_pb2_grpc.py to: 7 | # from . import receiver_pb2 as receiver__pb2 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Rust 2 | debug/ 3 | target/ 4 | Cargo.lock 5 | 6 | # Node 7 | node_modules 8 | build 9 | .svelte-kit 10 | .output 11 | .vercel 12 | 13 | # OS 14 | .ds_store 15 | 16 | # Env 17 | .env 18 | .env.* 19 | !.env.example 20 | !.env.test 21 | 22 | # Vite 23 | vite.config.js.timestamp-* 24 | vite.config.ts.timestamp-* 25 | 26 | # Python 27 | __pycache__/ 28 | .venv/ 29 | -------------------------------------------------------------------------------- /dashboard/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ❓ Ask Question 3 | about: Ask a general question about the project or its features. 4 | title: "[Q] " 5 | labels: question 6 | --- 7 | 8 | - [ ] I have searched the issues and discussions for a similar question. 9 | - [ ] I have read the project's documentation and guidelines. 10 | 11 | ### Question 12 | 13 | 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the application 2 | FROM rust:bullseye AS builder 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y protobuf-compiler libprotobuf-dev 5 | WORKDIR /phantasm 6 | COPY . . 7 | RUN cargo build --release 8 | 9 | # Build the application image 10 | FROM debian:bullseye-slim 11 | COPY --from=builder /phantasm/target/release/phantasm /usr/local/bin/phantasm 12 | EXPOSE 2505 2510 13 | ENTRYPOINT ["phantasm"] 14 | -------------------------------------------------------------------------------- /dashboard/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Phantasm 8 | %sveltekit.head% 9 | 10 | 11 |
%sveltekit.body%
12 | 13 | 14 | -------------------------------------------------------------------------------- /dashboard/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine AS builder 2 | WORKDIR /dashboard 3 | COPY package*.json . 4 | RUN npm ci 5 | COPY . . 6 | RUN npm run build 7 | RUN npm prune --production 8 | 9 | FROM node:18-alpine AS production 10 | WORKDIR /dashboard 11 | COPY --from=builder /dashboard/build ./build 12 | COPY --from=builder /dashboard/node_modules ./node_modules 13 | COPY --from=builder /dashboard/package.json ./package.json 14 | EXPOSE 2515 15 | ENV PORT=2515 16 | ENV NODE_ENV=production 17 | CMD ["node", "build"] 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🛠️ Feature Request 3 | about: Request a new feature or an improvement to an existing feature. 4 | title: "[FEAT] " 5 | labels: enhancement 6 | --- 7 | 8 | ### Feature Description 9 | 10 | 11 | 12 | ### Potential Solution 13 | 14 | 15 | 16 | ### Additional Context 17 | 18 | 19 | -------------------------------------------------------------------------------- /dashboard/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | export type Connection = { 2 | id: string 3 | name: string 4 | address: string 5 | } 6 | 7 | export type Alert = { 8 | id: string 9 | type: "success" | "error" 10 | message: string 11 | } 12 | 13 | export type ApprovalRequest = { 14 | id: string 15 | name: string 16 | parameters: string 17 | context: string 18 | } 19 | 20 | export type ApprovalResponse = { 21 | id: string 22 | approved: boolean 23 | parameters: string 24 | approver: Approver 25 | } 26 | 27 | export type Approver = { 28 | name: string 29 | email: string 30 | } 31 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/cards/alert.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |

{alert.message}

9 |
10 | 11 | 25 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/utils/wordmark.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 | Logo 21 | Phantasm 22 |
23 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/buttons/action.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 24 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "phantasm" 3 | version = "0.1.2" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] } 8 | tokio-tungstenite = "0.24.0" 9 | futures = "0.3.31" 10 | clap = "4.5.20" 11 | 12 | # gRPC 13 | tonic = "0.12.3" 14 | prost = "0.13.3" 15 | 16 | # Tracing 17 | tracing = "0.1.40" 18 | tracing-subscriber = "0.3.18" 19 | 20 | # Serialization 21 | serde = { version = "1.0.210", features = ["derive"] } 22 | serde_json = "1.0.128" 23 | 24 | # Utils 25 | uuid = { version = "1.10.0", features = ["v4", "serde", "fast-rng"] } 26 | dotenv = "0.15.0" 27 | 28 | [build-dependencies] 29 | tonic-build = "0.12" 30 | -------------------------------------------------------------------------------- /.github/workflows/dashboard-ci.yml: -------------------------------------------------------------------------------- 1 | name: Quality Check Dashboard 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | pull_request: 7 | paths: 8 | - "dashboard/**" 9 | 10 | push: 11 | branches: 12 | - main 13 | paths: 14 | - "dashboard/**" 15 | 16 | jobs: 17 | ci: 18 | name: Check Code Quality 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout Code 22 | uses: actions/checkout@v4 23 | 24 | - name: Install Dependencies 25 | run: | 26 | cd dashboard 27 | npm install 28 | 29 | - name: Run Linting & Formatting Check 30 | run: | 31 | cd dashboard 32 | npm run lint 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐞 Report Bug 3 | about: Report an unexpected behavior or a malfunctioning feature. 4 | title: "[BUG] " 5 | labels: bug 6 | --- 7 | 8 | ### Bug Description 9 | 10 | 11 | 12 | ### Steps to Reproduce 13 | 14 | 15 | 16 | 1. Import the library in ... 17 | 2. Initialize the object with ... 18 | 3. Call the function ... 19 | 20 | ### Expected Behavior 21 | 22 | 23 | 24 | ### Additional Context 25 | 26 | 27 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/buttons/basic.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Colors for better visibility in output 2 | GREEN := \033[0;32m 3 | BOLD := \033[1m 4 | RESET := \033[0m 5 | 6 | .PHONY: all 7 | all: 8 | @echo "Phantasm Makefile for Developers" 9 | @echo "" 10 | @echo "$(BOLD)Usage$(RESET): make " 11 | @echo "" 12 | @echo "$(BOLD)Available Target$(RESET)" 13 | @echo " - generate_grpc_stubs: Generate gRPC stubs for clients" 14 | 15 | .PHONY: generate_grpc_stubs 16 | generate_grpc_stubs: 17 | @echo "Generating gRPC stubs..." 18 | @python -m grpc_tools.protoc -I./protos \ 19 | --python_out=./clients/python/phantasmpy/stubs \ 20 | --grpc_python_out=./clients/python/phantasmpy/stubs \ 21 | ./protos/*.proto 22 | 23 | @echo "$(GREEN)gRPC stubs generated successfully!$(RESET)" 24 | -------------------------------------------------------------------------------- /.github/workflows/sdk-python-cd.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Python Client 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | env: 7 | PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} 8 | 9 | jobs: 10 | publish-package: 11 | environment: Clients 12 | name: Publish Python Package 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Code 16 | uses: actions/checkout@v4 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v5 20 | with: 21 | python-version: "3.x" 22 | 23 | - name: Install Poetry 24 | run: curl -sSL https://install.python-poetry.org | python3 - 25 | 26 | - name: Publish to PyPI 27 | run: | 28 | cd clients/python 29 | poetry publish -u __token__ -p $PYPI_TOKEN --build 30 | -------------------------------------------------------------------------------- /.github/workflows/.note: -------------------------------------------------------------------------------- 1 | This directory contains GitHub Actions workflows for Phantasm. 2 | 3 | There are 3 targets of the workflows: 4 | - server: Related to the receiver and the coordinator servers. 5 | - dashboard: Related to the web-based dashboard. 6 | - sdk-*: Related to the language-specific SDKs. 7 | 8 | There are 2 types of workflows: 9 | - [target]-ci.yml: Workflow for checking the code quality and running tests. 10 | - [target]-cd.yml: Workflow for building and publishing the package. 11 | 12 | This setup is made to isolate the CI and CD workflows only for the changes 13 | made in the specific target. For example, if we only change the server code, 14 | only the server-ci.yml and server-cd.yml workflows will be triggered. 15 | 16 | NOTE: Please follow the existing naming convention for the workflow files. 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | 4 | 5 | Fixes # 6 | 7 | ### How Has This Been Tested? 8 | 9 | 10 | 11 | 12 | - [ ] New and existing unit tests pass locally with my changes. 13 | - [ ] I have added tests that prove my changes are working as expected. 14 | 15 | ### Checklist 16 | 17 | - [ ] I have performed a self-review of my own code. 18 | - [ ] I have commented my code, particularly in hard-to-understand areas. 19 | - [ ] I have made corresponding changes to the documentation. 20 | 21 | ### Additional Context 22 | 23 | 24 | -------------------------------------------------------------------------------- /dashboard/eslint.config.js: -------------------------------------------------------------------------------- 1 | import eslint from "@eslint/js" 2 | import prettier from "eslint-config-prettier" 3 | import svelte from "eslint-plugin-svelte" 4 | import globals from "globals" 5 | import tseslint from "typescript-eslint" 6 | 7 | export default tseslint.config( 8 | eslint.configs.recommended, 9 | prettier, 10 | ...tseslint.configs.recommended, 11 | ...svelte.configs["flat/recommended"], 12 | ...svelte.configs["flat/prettier"], 13 | { 14 | languageOptions: { 15 | globals: { 16 | ...globals.browser, 17 | ...globals.node 18 | } 19 | } 20 | }, 21 | { 22 | files: ["**/*.svelte"], 23 | languageOptions: { 24 | parserOptions: { 25 | parser: tseslint.parser 26 | } 27 | } 28 | }, 29 | { 30 | ignores: ["build/", ".svelte-kit/", "dist/"] 31 | } 32 | ) 33 | -------------------------------------------------------------------------------- /clients/python/phantasmpy/types.py: -------------------------------------------------------------------------------- 1 | import json 2 | from typing import Any 3 | 4 | 5 | class HeartbeatResponse: 6 | version: str 7 | 8 | def __init__(self, version: str): 9 | self.version = version 10 | 11 | def __str__(self): 12 | return f"version: {self.version}" 13 | 14 | 15 | class GetApprovalResponse: 16 | """Response returned by the get approval method. 17 | 18 | Properties: 19 | - approved: True if the operation is approved, False otherwise. 20 | - parameters: Parameters to be used in the operation. 21 | """ 22 | 23 | approved: bool 24 | parameters: Any 25 | 26 | def __init__(self, approved: bool, parameters: str): 27 | self.approved = approved 28 | self.parameters = json.loads(parameters) if parameters else None 29 | 30 | def __str__(self): 31 | displays = [ 32 | f"approved: {self.approved}", 33 | f"parameters: {self.parameters}", 34 | ] 35 | 36 | return "\n".join(displays) 37 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/inputs/field.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /dashboard/src/lib/components/modals/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#if show} 7 |