From 2dbed61cfd06da3b58ae2f36f036bf187f38d59f Mon Sep 17 00:00:00 2001 From: bitful-pannul Date: Mon, 28 Oct 2024 17:53:55 +0100 Subject: [PATCH 01/43] app_store UI: app icon css tweak --- kinode/packages/app_store/ui/src/index.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kinode/packages/app_store/ui/src/index.css b/kinode/packages/app_store/ui/src/index.css index 8ef50f76..6d7747e8 100644 --- a/kinode/packages/app_store/ui/src/index.css +++ b/kinode/packages/app_store/ui/src/index.css @@ -136,6 +136,8 @@ td { .app-icon { width: 64px; height: 64px; + min-width: 64px; + min-height: 64px; object-fit: cover; border-radius: var(--border-radius); } @@ -348,6 +350,13 @@ td { padding-bottom: 1rem; } +.home-button { + min-width: 48px; + min-height: 48px; + width: 48px; + height: 48px; +} + .app-screenshot { max-width: 200px; height: auto; From 9f7c945d96d53168d8df2e8e35de316603c5ad6d Mon Sep 17 00:00:00 2001 From: bitful-pannul Date: Mon, 28 Oct 2024 17:54:46 +0100 Subject: [PATCH 02/43] app_store UI: my-downloads -> my-apps page, enable uninstalling unlisted packages --- kinode/packages/app_store/ui/src/App.tsx | 6 +- .../app_store/ui/src/components/Header.tsx | 6 +- .../app_store/ui/src/constants/path.ts | 2 +- .../{MyDownloadsPage.tsx => MyAppsPage.tsx} | 144 +++++++++++++++++- kinode/packages/app_store/ui/vite.config.ts | 2 +- 5 files changed, 147 insertions(+), 13 deletions(-) rename kinode/packages/app_store/ui/src/pages/{MyDownloadsPage.tsx => MyAppsPage.tsx} (61%) diff --git a/kinode/packages/app_store/ui/src/App.tsx b/kinode/packages/app_store/ui/src/App.tsx index aa112f28..c2f3d14e 100644 --- a/kinode/packages/app_store/ui/src/App.tsx +++ b/kinode/packages/app_store/ui/src/App.tsx @@ -2,13 +2,13 @@ import React from "react"; import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; import Header from "./components/Header"; -import { APP_DETAILS_PATH, DOWNLOAD_PATH, MY_DOWNLOADS_PATH, PUBLISH_PATH, STORE_PATH } from "./constants/path"; +import { APP_DETAILS_PATH, DOWNLOAD_PATH, MY_APPS_PATH, PUBLISH_PATH, STORE_PATH } from "./constants/path"; import StorePage from "./pages/StorePage"; import AppPage from "./pages/AppPage"; import DownloadPage from "./pages/DownloadPage"; import PublishPage from "./pages/PublishPage"; -import MyDownloadsPage from "./pages/MyDownloadsPage"; +import MyAppsPage from "./pages/MyAppsPage"; const BASE_URL = import.meta.env.BASE_URL; @@ -22,7 +22,7 @@ function App() {
} /> - } /> + } /> } /> } /> } /> diff --git a/kinode/packages/app_store/ui/src/components/Header.tsx b/kinode/packages/app_store/ui/src/components/Header.tsx index b28695b0..14cc9d6d 100644 --- a/kinode/packages/app_store/ui/src/components/Header.tsx +++ b/kinode/packages/app_store/ui/src/components/Header.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import { STORE_PATH, PUBLISH_PATH, MY_DOWNLOADS_PATH } from '../constants/path'; +import { STORE_PATH, PUBLISH_PATH, MY_APPS_PATH } from '../constants/path'; import { ConnectButton } from '@rainbow-me/rainbowkit'; import { FaHome } from "react-icons/fa"; @@ -9,12 +9,12 @@ const Header: React.FC = () => {
diff --git a/kinode/packages/app_store/ui/src/constants/path.ts b/kinode/packages/app_store/ui/src/constants/path.ts index 0f422617..08f6c817 100644 --- a/kinode/packages/app_store/ui/src/constants/path.ts +++ b/kinode/packages/app_store/ui/src/constants/path.ts @@ -2,4 +2,4 @@ export const STORE_PATH = '/'; export const PUBLISH_PATH = '/publish'; export const APP_DETAILS_PATH = '/app'; export const DOWNLOAD_PATH = '/download'; -export const MY_DOWNLOADS_PATH = '/my-downloads'; +export const MY_APPS_PATH = '/my-apps'; diff --git a/kinode/packages/app_store/ui/src/pages/MyDownloadsPage.tsx b/kinode/packages/app_store/ui/src/pages/MyAppsPage.tsx similarity index 61% rename from kinode/packages/app_store/ui/src/pages/MyDownloadsPage.tsx rename to kinode/packages/app_store/ui/src/pages/MyAppsPage.tsx index edafaf4c..fa2af6f7 100644 --- a/kinode/packages/app_store/ui/src/pages/MyDownloadsPage.tsx +++ b/kinode/packages/app_store/ui/src/pages/MyAppsPage.tsx @@ -3,15 +3,41 @@ import { FaFolder, FaFile, FaChevronLeft, FaSync, FaRocket, FaSpinner, FaCheck, import useAppsStore from "../store"; import { DownloadItem, PackageManifest, PackageState } from "../types/Apps"; -export default function MyDownloadsPage() { - const { fetchDownloads, fetchDownloadsForApp, startMirroring, stopMirroring, installApp, removeDownload, fetchInstalled, installed } = useAppsStore(); +// Core packages that cannot be uninstalled +const CORE_PACKAGES = [ + "app_store:sys", + "contacts:sys", + "kino_updates:sys", + "terminal:sys", + "chess:sys", + "kns_indexer:sys", + "settings:sys", + "homepage:sys" +]; + +export default function MyAppsPage() { + const { + fetchDownloads, + fetchDownloadsForApp, + startMirroring, + stopMirroring, + installApp, + removeDownload, + fetchInstalled, + installed, + uninstallApp + } = useAppsStore(); + const [currentPath, setCurrentPath] = useState([]); const [items, setItems] = useState([]); const [isInstalling, setIsInstalling] = useState(false); + const [isUninstalling, setIsUninstalling] = useState(false); const [error, setError] = useState(null); const [showCapApproval, setShowCapApproval] = useState(false); const [manifest, setManifest] = useState(null); const [selectedItem, setSelectedItem] = useState(null); + const [showUninstallConfirm, setShowUninstallConfirm] = useState(false); + const [appToUninstall, setAppToUninstall] = useState(null); useEffect(() => { loadItems(); @@ -33,6 +59,35 @@ export default function MyDownloadsPage() { } }; + const initiateUninstall = (app: any) => { + const packageId = `${app.package_id.package_name}:${app.package_id.publisher_node}`; + if (CORE_PACKAGES.includes(packageId)) { + setError("Cannot uninstall core system packages"); + return; + } + setAppToUninstall(app); + setShowUninstallConfirm(true); + }; + + const handleUninstall = async () => { + if (!appToUninstall) return; + setIsUninstalling(true); + const packageId = `${appToUninstall.package_id.package_name}:${appToUninstall.package_id.publisher_node}`; + try { + await uninstallApp(packageId); + await fetchInstalled(); + await loadItems(); + setShowUninstallConfirm(false); + setAppToUninstall(null); + } catch (error) { + console.error('Uninstallation failed:', error); + setError(`Uninstallation failed: ${error instanceof Error ? error.message : String(error)}`); + } finally { + setIsUninstalling(false); + } + }; + + const navigateToItem = (item: DownloadItem) => { if (item.Dir) { setCurrentPath([...currentPath, item.Dir.name]); @@ -85,7 +140,6 @@ export default function MyDownloadsPage() { if (!versionHash) throw new Error('Invalid file name format'); - // Construct packageId by combining currentPath and remaining parts of the filename const packageId = [...currentPath, ...parts].join(':'); await installApp(packageId, versionHash); @@ -121,8 +175,48 @@ export default function MyDownloadsPage() { return (
-

Downloads

+

My Apps

+ + {/* Installed Apps Section */}
+

Installed Apps

+ + + + + + + + + {Object.values(installed).map((app) => { + const packageId = `${app.package_id.package_name}:${app.package_id.publisher_node}`; + const isCore = CORE_PACKAGES.includes(packageId); + return ( + + + + + ); + })} + +
Package IDActions
{packageId} + {isCore ? ( + Core Package + ) : ( + + )} +
+
+ + {/* Downloads Section */} +
+

Downloads

{currentPath.length > 0 && (
)} + {/* Uninstall Confirmation Modal */} + {showUninstallConfirm && appToUninstall && ( +
+
+

Confirm Uninstall

+
+ Are you sure you want to uninstall this app? +
+
+ Package ID: {`${appToUninstall.package_id.package_name}:${appToUninstall.package_id.publisher_node}`} +
+ {appToUninstall.metadata?.name && ( +
+ Name: {appToUninstall.metadata.name} +
+ )} +
+ + +
+
+
+ )} + + + {showCapApproval && manifest && (
diff --git a/kinode/packages/app_store/ui/vite.config.ts b/kinode/packages/app_store/ui/vite.config.ts index 625a5e05..8a556bed 100644 --- a/kinode/packages/app_store/ui/vite.config.ts +++ b/kinode/packages/app_store/ui/vite.config.ts @@ -17,7 +17,7 @@ The format is "/" + "process_name:package_name:publisher_node" const BASE_URL = `/main:app_store:sys`; // This is the proxy URL, it must match the node you are developing against -const PROXY_URL = (process.env.VITE_NODE_URL || 'http://127.0.0.1:8080').replace('localhost', '127.0.0.1'); +const PROXY_URL = (process.env.VITE_NODE_URL || 'http://127.0.0.1:8080'); console.log('process.env.VITE_NODE_URL', process.env.VITE_NODE_URL, PROXY_URL); From ecf3618b7bd9102b6de64d8871a7b7dc0ed1845f Mon Sep 17 00:00:00 2001 From: bitful-pannul Date: Wed, 30 Oct 2024 22:26:41 +0100 Subject: [PATCH 03/43] fakenet: update addresses --- kinode/packages/app_store/chain/src/lib.rs | 2 +- kinode/packages/kns_indexer/kns_indexer/src/lib.rs | 2 +- kinode/src/fakenet.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kinode/packages/app_store/chain/src/lib.rs b/kinode/packages/app_store/chain/src/lib.rs index b0aadfa3..66db5995 100644 --- a/kinode/packages/app_store/chain/src/lib.rs +++ b/kinode/packages/app_store/chain/src/lib.rs @@ -59,7 +59,7 @@ const CHAIN_TIMEOUT: u64 = 60; // 60s #[cfg(not(feature = "simulation-mode"))] const KIMAP_ADDRESS: &'static str = kimap::KIMAP_ADDRESS; // optimism #[cfg(feature = "simulation-mode")] -const KIMAP_ADDRESS: &str = "0xEce71a05B36CA55B895427cD9a440eEF7Cf3669D"; +const KIMAP_ADDRESS: &str = "0x9CE8cCD2932DC727c70f9ae4f8C2b68E6Abed58C"; const DELAY_MS: u64 = 1_000; // 1s diff --git a/kinode/packages/kns_indexer/kns_indexer/src/lib.rs b/kinode/packages/kns_indexer/kns_indexer/src/lib.rs index eaba1e72..765e36e1 100644 --- a/kinode/packages/kns_indexer/kns_indexer/src/lib.rs +++ b/kinode/packages/kns_indexer/kns_indexer/src/lib.rs @@ -23,7 +23,7 @@ wit_bindgen::generate!({ #[cfg(not(feature = "simulation-mode"))] const KIMAP_ADDRESS: &'static str = kimap::KIMAP_ADDRESS; // optimism #[cfg(feature = "simulation-mode")] -const KIMAP_ADDRESS: &'static str = "0xEce71a05B36CA55B895427cD9a440eEF7Cf3669D"; // local +const KIMAP_ADDRESS: &'static str = "0x9CE8cCD2932DC727c70f9ae4f8C2b68E6Abed58C"; // local #[cfg(not(feature = "simulation-mode"))] const CHAIN_ID: u64 = kimap::KIMAP_CHAIN_ID; // optimism diff --git a/kinode/src/fakenet.rs b/kinode/src/fakenet.rs index 031b56d5..32df01dd 100644 --- a/kinode/src/fakenet.rs +++ b/kinode/src/fakenet.rs @@ -13,15 +13,15 @@ use std::str::FromStr; use crate::{keygen, sol::*, KIMAP_ADDRESS, MULTICALL_ADDRESS}; // TODO move these into contracts registry, doublecheck optimism deployments -const FAKE_DOTDEV_TBA: &str = "0x1a5447E634aa056Fa302E48630Da8425EC15A53A"; -const FAKE_DOTOS_TBA: &str = "0xF5FaB379Eb87599d7B5BaBeDDEFe6EfDEC6164b0"; -const _FAKE_ZEROTH_TBA: &str = "0x02dd7FB5ca377b1a6E2960EB139aF390a24D28FA"; +const FAKE_DOTDEV_TBA: &str = "0x27e913BF6dcd08E9E68530812B277224Be07890B"; +const FAKE_DOTOS_TBA: &str = "0xC026fE4950c12AdACF284689d900AcC74987c555"; +const _FAKE_ZEROTH_TBA: &str = "0x33b687295Cb095d9d962BA83732c67B96dffC8eA"; -const KINO_ACCOUNT_IMPL: &str = "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"; +const KINO_ACCOUNT_IMPL: &str = "0x00ee0e0d00F01f6FF3aCcBA2986E07f99181b9c2"; const MULTICALL: &str = "0xcA11bde05977b3631167028862bE2a173976CA11"; -const KIMAP: &str = "0xEce71a05B36CA55B895427cD9a440eEF7Cf3669D"; +const KIMAP: &str = "0x9CE8cCD2932DC727c70f9ae4f8C2b68E6Abed58C"; /// Attempts to connect to a local anvil fakechain, /// registering a name with its KiMap contract. From bd00406646e7987d17fce1cc4279205274ff2c99 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 4 Nov 2024 08:25:43 -0500 Subject: [PATCH 04/43] add redirect param to login page for loads where user already has cookie --- kinode/src/http/login.html | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kinode/src/http/login.html b/kinode/src/http/login.html index 6d197345..afcff2ef 100644 --- a/kinode/src/http/login.html +++ b/kinode/src/http/login.html @@ -231,7 +231,18 @@ } }); }); + + // Check for redirect parameter on page load + document.addEventListener("DOMContentLoaded", () => { + const urlParams = new URLSearchParams(window.location.search); + const redirectPath = urlParams.get('redirect'); + if (redirectPath) { + // Ensure the redirect path starts with a slash + const path = redirectPath.startsWith('/') ? redirectPath : '/' + redirectPath; + window.location.href = path; + } + }); - + \ No newline at end of file From 2b001b48d67deb95f6d40e32d8810a9e8b47d614 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 4 Nov 2024 09:21:37 -0500 Subject: [PATCH 05/43] 0.9.7->0.9.8 --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- kinode/Cargo.toml | 2 +- lib/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a10ae32f..abf0289a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -3652,7 +3652,7 @@ dependencies = [ [[package]] name = "kinode" -version = "0.9.7" +version = "0.9.8" dependencies = [ "aes-gcm", "alloy 0.2.1", @@ -3710,7 +3710,7 @@ dependencies = [ [[package]] name = "kinode_lib" -version = "0.9.7" +version = "0.9.8" dependencies = [ "lib", ] @@ -3855,7 +3855,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "lib" -version = "0.9.7" +version = "0.9.8" dependencies = [ "alloy 0.2.1", "anyhow", @@ -5747,7 +5747,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "snow" version = "0.9.0" -source = "git+https://github.com/dr-frmr/snow?branch=dr/extract_cipherstates#1d4eb5f6747aa59aabb32bbbe698fb4bb7dfb9a4" +source = "git+https://github.com/dr-frmr/snow?branch=dr%2Fextract_cipherstates#1d4eb5f6747aa59aabb32bbbe698fb4bb7dfb9a4" dependencies = [ "aes-gcm", "blake2", diff --git a/Cargo.toml b/Cargo.toml index ec72600a..d18ee061 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kinode_lib" authors = ["KinodeDAO"] -version = "0.9.7" +version = "0.9.8" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" diff --git a/kinode/Cargo.toml b/kinode/Cargo.toml index 67fecd9c..83de1b89 100644 --- a/kinode/Cargo.toml +++ b/kinode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kinode" authors = ["KinodeDAO"] -version = "0.9.7" +version = "0.9.8" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 99b064b7..c0431f08 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lib" authors = ["KinodeDAO"] -version = "0.9.7" +version = "0.9.8" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" From ec66b58f2b728804c67391769c55a5fae317c97d Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 4 Nov 2024 13:43:24 -0500 Subject: [PATCH 06/43] WIP --- kinode/src/http/login.html | 11 ----------- kinode/src/http/server.rs | 20 +++++++++++++++++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/kinode/src/http/login.html b/kinode/src/http/login.html index afcff2ef..680080c7 100644 --- a/kinode/src/http/login.html +++ b/kinode/src/http/login.html @@ -231,17 +231,6 @@ } }); }); - - // Check for redirect parameter on page load - document.addEventListener("DOMContentLoaded", () => { - const urlParams = new URLSearchParams(window.location.search); - const redirectPath = urlParams.get('redirect'); - if (redirectPath) { - // Ensure the redirect path starts with a slash - const path = redirectPath.startsWith('/') ? redirectPath : '/' + redirectPath; - window.location.href = path; - } - }); diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index 7481d979..6fc57368 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -294,6 +294,8 @@ async fn serve( .or(warp::post() .and(warp::body::content_length_limit(1024 * 16)) .and(warp::body::json()) + .and(warp::filters::host::optional()) + .and(warp::query::>()) .and(warp::any().map(move || cloned_our.clone())) .and(warp::any().map(move || encoded_keyfile.clone())) .and_then(login_handler)), @@ -324,7 +326,12 @@ async fn serve( /// handle non-GET requests on /login. if POST, validate password /// and return auth token, which will be stored in a cookie. +/// +/// if redirect is provided in URL, such as ?redirect=/chess:chess:sys/, +/// the browser will be redirected to that path after successful login. async fn login_handler( + host: Option, + query_params: HashMap, info: LoginInfo, our: Arc, encoded_keyfile: Arc>, @@ -354,7 +361,11 @@ async fn login_handler( let mut response = warp::reply::with_status( warp::reply::json(&base64_standard.encode(encoded_keyfile.to_vec())), - StatusCode::OK, + if let Some(redirect) = query_params.get("redirect") { + StatusCode::FOUND + } else { + StatusCode::OK + }, ) .into_response(); @@ -366,6 +377,13 @@ async fn login_handler( match HeaderValue::from_str(&cookie) { Ok(v) => { response.headers_mut().append("set-cookie", v); + if let Some(redirect) = query_params.get("redirect") { + response.headers_mut().append( + "Location", + HeaderValue::from_str(&format!("{}{redirect}", host.unwrap().host())) + .unwrap(), + ); + } Ok(response) } Err(e) => Ok(warp::reply::with_status( From a703b2c916e0820eaeeeb38dc71b0282241db138 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 01:59:31 +0000 Subject: [PATCH 07/43] Format Rust code using rustfmt --- kinode/src/kernel/process.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/kinode/src/kernel/process.rs b/kinode/src/kernel/process.rs index 093aa7e8..375fa3ac 100644 --- a/kinode/src/kernel/process.rs +++ b/kinode/src/kernel/process.rs @@ -507,12 +507,10 @@ pub async fn make_process_loop( reinitialize.await; None } - Some(wait_till) => { - Some(tokio::spawn(async move { - tokio::time::sleep_until(wait_till).await; - reinitialize.await; - })) - } + Some(wait_till) => Some(tokio::spawn(async move { + tokio::time::sleep_until(wait_till).await; + reinitialize.await; + })), }; *restart_backoff_lock = Some(RestartBackoff { next_soonest_restart_time, From be93b5a2907d2c9290185830a33144675a9b47bd Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Tue, 5 Nov 2024 14:48:01 -0500 Subject: [PATCH 08/43] fix: remove app store secure subdomain from links --- kinode/packages/app_store/ui/src/components/Header.tsx | 2 +- kinode/packages/app_store/ui/src/pages/AppPage.tsx | 2 +- kinode/packages/app_store/ui/src/pages/DownloadPage.tsx | 2 +- kinode/packages/contacts/pkg/ui/script.js | 7 +------ 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/kinode/packages/app_store/ui/src/components/Header.tsx b/kinode/packages/app_store/ui/src/components/Header.tsx index 14cc9d6d..4bcc28e5 100644 --- a/kinode/packages/app_store/ui/src/components/Header.tsx +++ b/kinode/packages/app_store/ui/src/components/Header.tsx @@ -9,7 +9,7 @@ const Header: React.FC = () => {
+
); }; - export default Header; \ No newline at end of file diff --git a/kinode/packages/app_store/ui/src/components/ManifestDisplay.tsx b/kinode/packages/app_store/ui/src/components/ManifestDisplay.tsx new file mode 100644 index 00000000..9767e338 --- /dev/null +++ b/kinode/packages/app_store/ui/src/components/ManifestDisplay.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { ManifestResponse, PackageManifestEntry } from '../types/Apps'; + +interface ManifestDisplayProps { + manifestResponse: ManifestResponse; +} + +const capabilityMap: Record = { + 'vfs:distro:sys': 'Virtual Filesystem', + 'http_client:distro:sys': 'HTTP Client', + 'http_server:distro:sys': 'HTTP Server', + 'eth:distro:sys': 'Ethereum RPC access', + 'homepage:homepage:sys': 'Ability to add itself to homepage', + 'main:app_store:sys': 'App Store', + 'chain:app_store:sys': 'Chain', + 'terminal:terminal:sys': 'Terminal', +}; + +// note: we can do some future regex magic mapping here too! +// if includes("root") return WARNING +const transformCapabilities = (capabilities: any[]) => { + return capabilities.map(cap => capabilityMap[cap] || cap); +}; + + +const renderManifest = (manifest: PackageManifestEntry) => ( +
+

Process Name: {manifest.process_name}

+

Requests Network Access: {manifest.request_networking ? 'Yes' : 'No'}

+

Wants to Grant Capabilities: {transformCapabilities(manifest.grant_capabilities).join(', ') || 'None'}

+

Is Public: {manifest.public ? 'Yes' : 'No'}

+

Requests the Capabilities: {transformCapabilities(manifest.request_capabilities).join(', ') || 'None'}

+ {/*

Process Wasm Path: {manifest.process_wasm_path}

*/} + {/*

On Exit: {manifest.on_exit}

*/} +
+); + +const ManifestDisplay: React.FC = ({ manifestResponse }) => { + if (!manifestResponse) { + return

No manifest data available.

; + } + + const parsedManifests: PackageManifestEntry[] = JSON.parse(manifestResponse.manifest); + + return ( +
+ {parsedManifests.map((manifest, index) => ( +
+ {renderManifest(manifest)} +
+ ))} +
+ ); +}; + +export default ManifestDisplay; \ No newline at end of file diff --git a/kinode/packages/app_store/ui/src/components/NotificationBay.tsx b/kinode/packages/app_store/ui/src/components/NotificationBay.tsx new file mode 100644 index 00000000..fdefaf10 --- /dev/null +++ b/kinode/packages/app_store/ui/src/components/NotificationBay.tsx @@ -0,0 +1,135 @@ +import React, { ReactNode, useState } from 'react'; +import { FaBell, FaChevronDown, FaChevronUp, FaTrash, FaTimes } from 'react-icons/fa'; +import useAppsStore from '../store'; +import { Notification, NotificationAction } from '../types/Apps'; +import { useNavigate } from 'react-router-dom'; + + +interface ModalProps { + children: ReactNode; + onClose: () => void; +} + +const Modal: React.FC = ({ children, onClose }) => { + return ( +
+
+ + {children} +
+
+ ); +}; + +const NotificationBay: React.FC = () => { + const { notifications, removeNotification } = useAppsStore(); + const [isExpanded, setIsExpanded] = useState(false); + const [modalContent, setModalContent] = useState(null); + const navigate = useNavigate(); + + const handleActionClick = (action: NotificationAction) => { + switch (action.action.type) { + case 'modal': + const content = typeof action.action.modalContent === 'function' + ? action.action.modalContent() + : action.action.modalContent; + setModalContent(content); + break; + case 'click': + action.action.onClick?.(); + break; + case 'redirect': + if (action.action.path) { + navigate(action.action.path); + } + break; + } + }; + + const handleDismiss = (notificationId: string, event: React.MouseEvent) => { + event.stopPropagation(); // Prevent event bubbling + removeNotification(notificationId); + }; + + const renderNotification = (notification: Notification) => { + return ( +
+ {notification.renderContent ? ( + notification.renderContent(notification) + ) : ( + <> +
+

{notification.message}

+ {notification.type === 'download' && notification.metadata?.progress && ( +
+
+
+ )} +
+ + {notification.actions && ( +
+ {notification.actions.map((action, index) => ( + + ))} +
+ )} + + {!notification.persistent && ( + + )} + + )} +
+ ); + }; + + return ( + <> +
+ + + {isExpanded && ( +
+ {notifications.length === 0 ? ( +

All clear, no notifications!

+ ) : ( + notifications.map(renderNotification) + )} +
+ )} +
+ + {modalContent && ( + setModalContent(null)}> + {modalContent} + + )} + + ); +}; + +export default NotificationBay; \ No newline at end of file diff --git a/kinode/packages/app_store/ui/src/components/index.ts b/kinode/packages/app_store/ui/src/components/index.ts index 0d50b938..d2e77394 100644 --- a/kinode/packages/app_store/ui/src/components/index.ts +++ b/kinode/packages/app_store/ui/src/components/index.ts @@ -1,3 +1,5 @@ export { default as Header } from './Header'; export { default as MirrorSelector } from './MirrorSelector'; -export { default as PackageSelector } from './PackageSelector'; \ No newline at end of file +export { default as PackageSelector } from './PackageSelector'; +export { default as ManifestDisplay } from './ManifestDisplay'; +export { default as NotificationBay } from './NotificationBay'; \ No newline at end of file diff --git a/kinode/packages/app_store/ui/src/index.css b/kinode/packages/app_store/ui/src/index.css index 6d7747e8..928a72ca 100644 --- a/kinode/packages/app_store/ui/src/index.css +++ b/kinode/packages/app_store/ui/src/index.css @@ -49,6 +49,13 @@ a:hover { gap: 1rem; } +.header-right { + display: flex; + align-items: center; + gap: 1rem; + /* Provides consistent spacing between NotificationBay and ConnectButton */ +} + .header-left h1 { margin: 0; font-size: 1.5rem; @@ -432,4 +439,167 @@ td { .fa-spin { animation: spin 1s linear infinite; +} + +.manifest-display { + background-color: light-dark(var(--tan), var(--tasteful-dark)); + color: light-dark(var(--off-black), var(--off-white)); + padding: 1rem; + border-radius: var(--border-radius); + margin-bottom: 1rem; +} + +.manifest-item { + margin-bottom: 1rem; + padding: 1rem; + border: 1px solid var(--gray); + border-radius: var(--border-radius); + background-color: light-dark(var(--white), var(--off-black)); +} + +.manifest-item p { + margin: 0.5rem 0; +} + +.notification-bay { + position: relative; + margin-right: 1rem; +} + +.notification-button { + background: none; + border: none; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem; + color: light-dark(var(--off-black), var(--off-white)); +} + +.notification-details { + position: absolute; + top: 100%; + right: 0; + width: 320px; + max-height: 400px; + overflow-y: auto; + background-color: light-dark(var(--white), var(--tasteful-dark)); + border-radius: var(--border-radius); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + z-index: 1000; + padding: 0.5rem; +} + +.badge { + background-color: var(--orange); + color: var(--white); + border-radius: 50%; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + min-width: 1.5rem; + text-align: center; +} + +.notification-item { + display: flex; + align-items: center; + padding: 1rem; + margin: 0.5rem 0; + border-radius: var(--border-radius); + background-color: light-dark(var(--tan), var(--off-black)); + color: light-dark(var(--off-black), var(--off-white)); +} + +.notification-item.error { + background-color: light-dark(#ffe6e6, #4a2020); +} + +.notification-item.success { + background-color: light-dark(#e6ffe6, #204a20); +} + +.notification-item.warning { + background-color: light-dark(#fff3e6, #4a3820); +} + +.notification-item.download { + background-color: light-dark(#e6f3ff, #20304a); +} + +.notification-content { + flex: 1; + margin-right: 1rem; +} + +.notification-actions { + display: flex; + gap: 0.5rem; + margin-left: auto; +} + +.dismiss-button { + background: none; + border: none; + cursor: pointer; + color: light-dark(var(--gray), var(--off-white)); + padding: 0.25rem; +} + +.dismiss-button:hover { + color: var(--orange); +} + +.progress-bar { + margin-top: 0.5rem; + height: 4px; + background-color: light-dark(var(--white), var(--off-black)); + border-radius: 2px; + overflow: hidden; +} + +.progress { + height: 100%; + background-color: var(--orange); + transition: width 0.3s ease; +} + +/* Modal styles */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1100; +} + +.modal-content { + background-color: light-dark(var(--white), var(--tasteful-dark)); + color: light-dark(var(--off-black), var(--off-white)); + padding: 1.5rem; + border-radius: var(--border-radius); + position: relative; + max-width: 80%; + max-height: 80vh; + overflow-y: auto; +} + +.modal-close { + position: absolute; + top: 0.75rem; + right: 0.75rem; + background: none; + border: none; + cursor: pointer; + color: light-dark(var(--gray), var(--off-white)); + padding: 0.25rem; +} + +.modal-close:hover { + color: var(--orange); } \ No newline at end of file diff --git a/kinode/packages/app_store/ui/src/pages/DownloadPage.tsx b/kinode/packages/app_store/ui/src/pages/DownloadPage.tsx index 994e2c9c..50f6f2fd 100644 --- a/kinode/packages/app_store/ui/src/pages/DownloadPage.tsx +++ b/kinode/packages/app_store/ui/src/pages/DownloadPage.tsx @@ -2,7 +2,8 @@ import React, { useState, useEffect, useCallback, useMemo } from "react"; import { useParams } from "react-router-dom"; import { FaDownload, FaSpinner, FaChevronDown, FaChevronUp, FaRocket, FaTrash, FaPlay } from "react-icons/fa"; import useAppsStore from "../store"; -import { MirrorSelector } from '../components'; +import { MirrorSelector, ManifestDisplay } from '../components'; +import { ManifestResponse } from "../types/Apps"; export default function DownloadPage() { const { id } = useParams<{ id: string }>(); @@ -17,7 +18,7 @@ export default function DownloadPage() { removeDownload, clearAllActiveDownloads, fetchHomepageApps, - getLaunchUrl + getLaunchUrl, } = useAppsStore(); const [showMetadata, setShowMetadata] = useState(false); @@ -26,7 +27,7 @@ export default function DownloadPage() { const [showMyDownloads, setShowMyDownloads] = useState(false); const [isMirrorOnline, setIsMirrorOnline] = useState(null); const [showCapApproval, setShowCapApproval] = useState(false); - const [manifest, setManifest] = useState(null); + const [manifestResponse, setManifestResponse] = useState(null); const [isInstalling, setIsInstalling] = useState(false); const [isCheckingLaunch, setIsCheckingLaunch] = useState(false); const [launchPath, setLaunchPath] = useState(null); @@ -151,8 +152,12 @@ export default function DownloadPage() { const download = appDownloads.find(d => d.File && d.File.name === `${hash}.zip`); if (download?.File?.manifest) { try { - const manifestData = JSON.parse(download.File.manifest); - setManifest(manifestData); + const manifest_response: ManifestResponse = { + package_id: app.package_id, + version_hash: hash, + manifest: download.File.manifest + }; + setManifestResponse(manifest_response); setShowCapApproval(true); } catch (error) { console.error('Failed to parse manifest:', error); @@ -170,7 +175,7 @@ export default function DownloadPage() { setLaunchPath(null); installApp(id, versionData.hash).then(() => { setShowCapApproval(false); - setManifest(null); + setManifestResponse(null); fetchData(id); }); } @@ -337,13 +342,11 @@ export default function DownloadPage() { )}
- {showCapApproval && manifest && ( + {showCapApproval && manifestResponse && (

Approve Capabilities

-
-                            {JSON.stringify(manifest[0]?.request_capabilities || [], null, 2)}
-                        
+
)} -

App Details

+ + {isExpanded && ( +
+ {manifest.request_capabilities.length > 0 && ( +
+

Requested Capabilities:

+
    + {transformCapabilities(manifest.request_capabilities).map((cap, i) => ( +
  • {cap}
  • + ))} +
+
+ )} + + {manifest.grant_capabilities.length > 0 && ( +
+

Granted Capabilities:

+
    + {transformCapabilities(manifest.grant_capabilities).map((cap, i) => ( +
  • {cap}
  • + ))} +
+
+ )} +
+ )} +
+ ); +}; const ManifestDisplay: React.FC = ({ manifestResponse }) => { if (!manifestResponse) { @@ -45,9 +88,7 @@ const ManifestDisplay: React.FC = ({ manifestResponse }) = return (
{parsedManifests.map((manifest, index) => ( -
- {renderManifest(manifest)} -
+ ))}
); diff --git a/kinode/packages/app_store/ui/src/components/NotificationBay.tsx b/kinode/packages/app_store/ui/src/components/NotificationBay.tsx index fdefaf10..9454274a 100644 --- a/kinode/packages/app_store/ui/src/components/NotificationBay.tsx +++ b/kinode/packages/app_store/ui/src/components/NotificationBay.tsx @@ -25,6 +25,7 @@ const Modal: React.FC = ({ children, onClose }) => { const NotificationBay: React.FC = () => { const { notifications, removeNotification } = useAppsStore(); + const hasErrors = notifications.some(n => n.type === 'error'); const [isExpanded, setIsExpanded] = useState(false); const [modalContent, setModalContent] = useState(null); const navigate = useNavigate(); @@ -104,12 +105,16 @@ const NotificationBay: React.FC = () => { return ( <>
- {isExpanded && ( diff --git a/kinode/packages/app_store/ui/src/index.css b/kinode/packages/app_store/ui/src/index.css index 928a72ca..e83e6591 100644 --- a/kinode/packages/app_store/ui/src/index.css +++ b/kinode/packages/app_store/ui/src/index.css @@ -442,23 +442,87 @@ td { } .manifest-display { - background-color: light-dark(var(--tan), var(--tasteful-dark)); + background: light-dark(var(--white), var(--tasteful-dark)); + border-radius: var(--border-radius); + padding: 1rem; + max-width: 600px; +} + +.process-manifest { + margin-bottom: 0.5rem; + border: 1px solid light-dark(var(--gray), var(--off-black)); + border-radius: var(--border-radius); + overflow: hidden; +} + +.process-header { + width: 100%; + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1rem; + background: none; + border: none; + cursor: pointer; color: light-dark(var(--off-black), var(--off-white)); + transition: background-color 0.2s; +} + +.process-header:hover { + background: light-dark(var(--tan), var(--off-black)); +} + +.process-name { + flex: 1; + text-align: left; + font-weight: 500; +} + +.process-indicators { + display: flex; + gap: 0.5rem; + color: light-dark(var(--gray), var(--off-white)); +} + +.network-icon { + color: var(--orange); +} + +.capability-icon { + color: var(--blue); +} + +.private-icon { + color: var(--gray); +} + +.process-details { padding: 1rem; - border-radius: var(--border-radius); + background: light-dark(var(--tan), var(--off-black)); + border-top: 1px solid light-dark(var(--gray), var(--off-black)); +} + +.capability-section { margin-bottom: 1rem; } -.manifest-item { - margin-bottom: 1rem; - padding: 1rem; - border: 1px solid var(--gray); - border-radius: var(--border-radius); - background-color: light-dark(var(--white), var(--off-black)); +.capability-section:last-child { + margin-bottom: 0; } -.manifest-item p { - margin: 0.5rem 0; +.capability-section h4 { + margin: 0 0 0.5rem 0; + color: light-dark(var(--off-black), var(--off-white)); +} + +.capability-section ul { + margin: 0; + padding-left: 1.5rem; + color: light-dark(var(--gray), var(--off-white)); +} + +.capability-section li { + margin-bottom: 0.25rem; } .notification-bay { @@ -602,4 +666,51 @@ td { .modal-close:hover { color: var(--orange); +} + +.notification-button.has-errors { + animation: shake 0.82s cubic-bezier(.36, .07, .19, .97) both; +} + +.badge.error-badge { + background-color: var(--error-red); + animation: pulse 2s infinite; +} + +@keyframes shake { + + 10%, + 90% { + transform: translate3d(-1px, 0, 0); + } + + 20%, + 80% { + transform: translate3d(2px, 0, 0); + } + + 30%, + 50%, + 70% { + transform: translate3d(-4px, 0, 0); + } + + 40%, + 60% { + transform: translate3d(4px, 0, 0); + } +} + +@keyframes pulse { + 0% { + opacity: 1; + } + + 50% { + opacity: 0.6; + } + + 100% { + opacity: 1; + } } \ No newline at end of file From 016c34fbe86b52862e7b938a3aa3dba5e87d864d Mon Sep 17 00:00:00 2001 From: bitful-pannul Date: Fri, 8 Nov 2024 21:42:48 +0400 Subject: [PATCH 16/43] app_store ft_worker: do not create received zip file before first chunk --- .../packages/app_store/ft_worker/src/lib.rs | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/kinode/packages/app_store/ft_worker/src/lib.rs b/kinode/packages/app_store/ft_worker/src/lib.rs index b4f2b3ec..9c80ae2c 100644 --- a/kinode/packages/app_store/ft_worker/src/lib.rs +++ b/kinode/packages/app_store/ft_worker/src/lib.rs @@ -78,6 +78,7 @@ fn init(our: Address) { } // killswitch timer, 2 minutes. sender or receiver gets killed/cleaned up. + // TODO: killswitch update bubbles up to downloads process? timer::set_timer(120000, None); let start = std::time::Instant::now(); @@ -167,7 +168,11 @@ fn handle_receiver( package_id: &PackageId, version_hash: &str, ) -> anyhow::Result<()> { - // TODO: write to a temporary location first, then check hash as we go, then rename to final location. + let timer_address = Address::from_str("our@timer:distro:sys")?; + + let mut file: Option = None; + let mut size: Option = None; + let mut hasher = Sha256::new(); let package_dir = vfs::open_dir( &format!( @@ -179,16 +184,6 @@ fn handle_receiver( None, )?; - let timer_address = Address::from_str("our@timer:distro:sys")?; - - let mut file = vfs::open_file( - &format!("{}{}.zip", &package_dir.path, version_hash), - true, - None, - )?; - let mut size: Option = None; - let mut hasher = Sha256::new(); - loop { let message = await_message()?; if *message.source() == timer_address { @@ -200,7 +195,28 @@ fn handle_receiver( match message.body().try_into()? { DownloadRequests::Chunk(chunk) => { - handle_chunk(&mut file, &chunk, parent_process, &mut size, &mut hasher)?; + let bytes = if let Some(blob) = get_blob() { + blob.bytes + } else { + return Err(anyhow::anyhow!("ft_worker: got no blob in chunk request")); + }; + + if file.is_none() { + file = Some(vfs::open_file( + &format!("{}{}.zip", &package_dir.path, version_hash), + true, + None, + )?); + } + + handle_chunk( + file.as_mut().unwrap(), + &chunk, + parent_process, + &mut size, + &mut hasher, + &bytes, + )?; if let Some(s) = size { if chunk.offset + chunk.length >= s { let recieved_hash = format!("{:x}", hasher.finalize()); @@ -232,7 +248,7 @@ fn handle_receiver( let manifest_filename = format!("{}{}.json", package_dir.path, version_hash); - let contents = file.read()?; + let contents = file.as_mut().unwrap().read()?; extract_and_write_manifest(&contents, &manifest_filename)?; Request::new() @@ -292,15 +308,10 @@ fn handle_chunk( parent: &Address, size: &mut Option, hasher: &mut Sha256, + bytes: &[u8], ) -> anyhow::Result<()> { - let bytes = if let Some(blob) = get_blob() { - blob.bytes - } else { - return Err(anyhow::anyhow!("ft_worker: got no blob")); - }; - - file.write_all(&bytes)?; - hasher.update(&bytes); + file.write_all(bytes)?; + hasher.update(bytes); if let Some(total_size) = size { // let progress = ((chunk.offset + chunk.length) as f64 / *total_size as f64 * 100.0) as u64; From 9d1f2e56e00a04f4b3b6944cc9fb4ed9eab14fd4 Mon Sep 17 00:00:00 2001 From: bitful-pannul Date: Fri, 8 Nov 2024 21:43:19 +0400 Subject: [PATCH 17/43] app_store: respond with sender errors and show them on receiver UI --- .../packages/app_store/downloads/src/lib.rs | 72 ++++++++++++++++--- .../packages/app_store/ui/src/store/index.ts | 24 ++++--- 2 files changed, 79 insertions(+), 17 deletions(-) diff --git a/kinode/packages/app_store/downloads/src/lib.rs b/kinode/packages/app_store/downloads/src/lib.rs index 31c91f13..9755956a 100644 --- a/kinode/packages/app_store/downloads/src/lib.rs +++ b/kinode/packages/app_store/downloads/src/lib.rs @@ -209,19 +209,32 @@ fn handle_message( desired_version_hash, worker_address: our_worker.to_string(), })) + .expects_response(60) + .context(&download_request) .send()?; } DownloadRequests::RemoteDownload(download_request) => { - // this is a node requesting a download from us. - // check if we are mirroring. we should maybe implement some back and forth here. - // small handshake for started? but we do not really want to wait for that in this loop.. - // might be okay. implement. let RemoteDownloadRequest { package_id, desired_version_hash, worker_address, } = download_request; + let process_lib_package_id = package_id.clone().to_process_lib(); + + // check if we are mirroring, if not send back an error. + if !state.mirroring.contains(&process_lib_package_id) { + let resp = DownloadResponses::Err(DownloadError::NotMirroring); + Response::new().body(&resp).send()?; + return Ok(()); // return here, todo unify remote and local responses? + } + + if !download_zip_exists(&process_lib_package_id, &desired_version_hash) { + let resp = DownloadResponses::Err(DownloadError::FileNotFound); + Response::new().body(&resp).send()?; + return Ok(()); // return here, todo unify remote and local responses? + } + let target_worker = Address::from_str(&worker_address)?; let _ = spawn_send_transfer( our, @@ -230,6 +243,8 @@ fn handle_message( APP_SHARE_TIMEOUT, &target_worker, )?; + let resp = DownloadResponses::Success; + Response::new().body(&resp).send()?; } DownloadRequests::Progress(ref progress) => { // forward progress to main:app_store:sys, @@ -428,11 +443,34 @@ fn handle_message( } else { match message.body().try_into()? { Resp::Download(download_response) => { - // these are handled in line. - print_to_terminal( - 1, - &format!("got a weird download response: {:?}", download_response), - ); + // get context of the response. + // handled are errors or ok responses from a remote node. + + if let Some(context) = message.context() { + let download_request = serde_json::from_slice::(context)?; + match download_response { + DownloadResponses::Err(e) => { + Request::to(("our", "main", "app_store", "sys")) + .body(DownloadCompleteRequest { + package_id: download_request.package_id.clone(), + version_hash: download_request.desired_version_hash.clone(), + err: Some(e), + }) + .send()?; + } + DownloadResponses::Success => { + // todo: maybe we do something here. + print_to_terminal( + 1, + &format!( + "downloads: got success response from remote node: {:?}", + download_request + ), + ); + } + _ => {} + } + } } Resp::HttpClient(resp) => { let Some(context) = message.context() else { @@ -575,6 +613,22 @@ fn extract_and_write_manifest(file_contents: &[u8], manifest_path: &str) -> anyh Ok(()) } +/// Check if a download zip exists for a given package and version hash. +/// Used to check if we can share a package or not! +fn download_zip_exists(package_id: &PackageId, version_hash: &str) -> bool { + let filename = format!( + "/app_store:sys/downloads/{}:{}/{}.zip", + package_id.package_name, + package_id.publisher(), + version_hash + ); + let res = vfs::metadata(&filename, None); + match res { + Ok(meta) => meta.file_type == vfs::FileType::File, + Err(_e) => false, + } +} + fn get_manifest_hash(package_id: PackageId, version_hash: String) -> anyhow::Result { let package_dir = format!("{}/{}", "/app_store:sys/downloads", package_id.to_string()); let manifest_path = format!("{}/{}.json", package_dir, version_hash); diff --git a/kinode/packages/app_store/ui/src/store/index.ts b/kinode/packages/app_store/ui/src/store/index.ts index 48fc7d50..9a17f7b8 100644 --- a/kinode/packages/app_store/ui/src/store/index.ts +++ b/kinode/packages/app_store/ui/src/store/index.ts @@ -413,18 +413,26 @@ const useAppsStore = create()((set, get) => ({ } }); } else if (data.kind === 'complete') { - const { package_id, version_hash } = data.data; + const { package_id, version_hash, error } = data.data; const appId = `${package_id.package_name}:${package_id.publisher_node}:${version_hash}`; get().clearActiveDownload(appId); - get().removeNotification(`download-${appId}`); - get().addNotification({ - id: `complete-${appId}`, - type: 'success', - message: `Download complete: ${package_id.package_name}`, - timestamp: Date.now(), - }); + if (error) { + get().addNotification({ + id: `error-${appId}`, + type: 'error', + message: `Download failed for ${package_id.package_name}: ${error}`, + timestamp: Date.now(), + }); + } else { + get().addNotification({ + id: `complete-${appId}`, + type: 'success', + message: `Download complete: ${package_id.package_name}`, + timestamp: Date.now(), + }); + } get().fetchData(`${package_id.package_name}:${package_id.publisher_node}`); } From 325d5f3ce1fd76f831d2eb9b2f037e19ac4af7b8 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Fri, 8 Nov 2024 17:18:49 -0800 Subject: [PATCH 18/43] bump version to 0.9.9 --- Cargo.toml | 2 +- kinode/Cargo.toml | 2 +- lib/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d18ee061..2ea883de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kinode_lib" authors = ["KinodeDAO"] -version = "0.9.8" +version = "0.9.9" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" diff --git a/kinode/Cargo.toml b/kinode/Cargo.toml index 83de1b89..a32942de 100644 --- a/kinode/Cargo.toml +++ b/kinode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kinode" authors = ["KinodeDAO"] -version = "0.9.8" +version = "0.9.9" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index c0431f08..9a868221 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lib" authors = ["KinodeDAO"] -version = "0.9.8" +version = "0.9.9" edition = "2021" description = "A general-purpose sovereign cloud computing platform" homepage = "https://kinode.org" From ffb43bb626cc4e5a6b696e96f54227de1214a4d6 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Fri, 8 Nov 2024 17:21:57 -0800 Subject: [PATCH 19/43] vfs: fix bad change from d3ee13e that broke caps --- kinode/src/vfs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kinode/src/vfs.rs b/kinode/src/vfs.rs index 6743d685..a34a6f74 100644 --- a/kinode/src/vfs.rs +++ b/kinode/src/vfs.rs @@ -343,7 +343,8 @@ async fn handle_request( // current prepend to filepaths needs to be: /package_id/drive/path let (package_id, drive, rest) = parse_package_and_drive(&request.path, &vfs_path)?; - let drive = format!("{package_id}/{drive}"); + // must have prepended `/` here or else it messes up caps downstream, e.g. in run-tests + let drive = format!("/{package_id}/{drive}"); let action = request.action; let path = PathBuf::from(&request.path); From 6f0a47556e39e979f1fc8321aa540d4b50cfce9f Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 11 Nov 2024 14:22:29 -0500 Subject: [PATCH 20/43] surface auto_install error --- kinode/packages/app_store/app_store/src/lib.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/kinode/packages/app_store/app_store/src/lib.rs b/kinode/packages/app_store/app_store/src/lib.rs index 8ed6aab7..ca9e553e 100644 --- a/kinode/packages/app_store/app_store/src/lib.rs +++ b/kinode/packages/app_store/app_store/src/lib.rs @@ -188,24 +188,20 @@ fn handle_message( .unwrap_or(false); if should_auto_install { - print_to_terminal(1, "auto_install:main, manifest_hash match"); if let Err(e) = utils::install(&package_id, None, &version_hash, state, &our.node) { if let Some(package) = state.packages.get_mut(&process_lib_package_id) { package.pending_update_hash = Some(version_hash); } - print_to_terminal(1, &format!("error auto_installing package: {e}")); + println!("error auto-installing package: {e}"); } else { - println!( - "auto_installed update for package: {:?}", - &process_lib_package_id - ); + println!("auto-installed update for package: {process_lib_package_id}"); } } else { if let Some(package) = state.packages.get_mut(&process_lib_package_id) { package.pending_update_hash = Some(version_hash); - print_to_terminal(1, "auto_install:main, manifest_hash do not match"); + println!("error auto-installing package: manifest hash mismatch"); } } } From 348155e165bcef81a90ead20775e608925fddb56 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 11 Nov 2024 15:02:15 -0500 Subject: [PATCH 21/43] fix: blog widget println import --- Cargo.lock | 6 +++--- kinode/packages/kino_updates/blog/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index abf0289a..a7c601ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3652,7 +3652,7 @@ dependencies = [ [[package]] name = "kinode" -version = "0.9.8" +version = "0.9.9" dependencies = [ "aes-gcm", "alloy 0.2.1", @@ -3710,7 +3710,7 @@ dependencies = [ [[package]] name = "kinode_lib" -version = "0.9.8" +version = "0.9.9" dependencies = [ "lib", ] @@ -3855,7 +3855,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "lib" -version = "0.9.8" +version = "0.9.9" dependencies = [ "alloy 0.2.1", "anyhow", diff --git a/kinode/packages/kino_updates/blog/src/lib.rs b/kinode/packages/kino_updates/blog/src/lib.rs index 714b88f1..5b3dadc2 100644 --- a/kinode/packages/kino_updates/blog/src/lib.rs +++ b/kinode/packages/kino_updates/blog/src/lib.rs @@ -1,4 +1,4 @@ -use kinode_process_lib::{call_init, http, timer, Address, Request}; +use kinode_process_lib::{call_init, http, println, timer, Address, Request}; use serde::{Deserialize, Serialize}; wit_bindgen::generate!({ From 446654a4fbe5a427896217e44515a511676a1c59 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 11 Nov 2024 15:25:00 -0500 Subject: [PATCH 22/43] security: deescalate perm given in build-release.py --- scripts/build-release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-release.py b/scripts/build-release.py index bd36ac1e..f9d09c0a 100755 --- a/scripts/build-release.py +++ b/scripts/build-release.py @@ -60,7 +60,7 @@ def build_and_move(feature, tmp_dir, architecture, os_name): source_path = f"target/release/{binary_name}" dest_path = os.path.join(tmp_dir, binary_name) shutil.move(source_path, dest_path) - os.chmod(dest_path, 0o775) + os.chmod(dest_path, 0o644) # Create a zip archive of the binary zip_path = os.path.join(tmp_dir, zip_name) From df1dbb5a9da207e03a6016f516d038d2fc245b6c Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 11 Nov 2024 16:32:33 -0500 Subject: [PATCH 23/43] security: add salting to node password hashing --- kinode/src/http/login.html | 5 +- kinode/src/main.rs | 15 +++- .../register-ui/src/pages/ImportKeyfile.tsx | 19 ++++- kinode/src/register-ui/src/pages/Login.tsx | 3 +- .../src/register-ui/src/pages/SetPassword.tsx | 3 +- kinode/src/register.rs | 79 +------------------ 6 files changed, 38 insertions(+), 86 deletions(-) diff --git a/kinode/src/http/login.html b/kinode/src/http/login.html index 6d197345..87106883 100644 --- a/kinode/src/http/login.html +++ b/kinode/src/http/login.html @@ -185,7 +185,8 @@ document.getElementById("loading").style.display = "flex"; // sha256 hash password using crypto-js - const hashHex = '0x' + CryptoJS.SHA256(password).toString(CryptoJS.enc.Hex); + const salted = ['${node}', password].join(""); + const hashHex = '0x' + CryptoJS.SHA256(salted).toString(CryptoJS.enc.Hex); const result = await fetch("/login", { method: "POST", @@ -234,4 +235,4 @@ - + \ No newline at end of file diff --git a/kinode/src/main.rs b/kinode/src/main.rs index 02f9f578..4ba0cfbe 100644 --- a/kinode/src/main.rs +++ b/kinode/src/main.rs @@ -839,7 +839,20 @@ async fn login_with_password( .await .expect("could not read keyfile"); - let password_hash = format!("0x{}", hex::encode(Sha256::digest(password))); + let (username, _, _, _, _, _) = + serde_json::from_slice::<(String, Vec, Vec, Vec, Vec, Vec)>( + &disk_keyfile, + ) + .or_else(|_| { + bincode::deserialize::<(String, Vec, Vec, Vec, Vec, Vec)>( + &disk_keyfile, + ) + }) + .unwrap(); + + let salted = [username.as_bytes(), password.as_bytes()].concat(); + + let password_hash = format!("0x{}", hex::encode(Sha256::digest(salted))); let provider = Arc::new(register::connect_to_provider(maybe_rpc).await); diff --git a/kinode/src/register-ui/src/pages/ImportKeyfile.tsx b/kinode/src/register-ui/src/pages/ImportKeyfile.tsx index 735cccbb..ff1d6070 100644 --- a/kinode/src/register-ui/src/pages/ImportKeyfile.tsx +++ b/kinode/src/register-ui/src/pages/ImportKeyfile.tsx @@ -24,6 +24,7 @@ function ImportKeyfile({ const [pwVet, _setPwVet] = useState(false); const [pwDebounced, _setPwDebounced] = useState(false); const [loading, setLoading] = useState(false); + const [knsName, setKnsName] = useState(""); useEffect(() => { document.title = "Import Keyfile"; @@ -55,7 +56,8 @@ function ImportKeyfile({ try { if (keyErrs.length === 0 && localKey !== null) { - let hashed_password = sha256(toBytes(pw)); + let salted = [knsName, pw].join(""); + let hashed_password = sha256(toBytes(salted)); const result = await fetch("/import-keyfile", { method: "POST", @@ -103,8 +105,19 @@ function ImportKeyfile({ {localKeyFileName &&

{localKeyFileName}

} -
-

2. Enter Password

+
+
+

2. Enter Node ID

+ +
+
+

3. Enter Password

{ setLoading(true); - let hashed_password = sha256(toBytes(pw)); + let salted = [knsName, pw].join(""); + let hashed_password = sha256(toBytes(salted)); let owner = address; let timestamp = Date.now(); diff --git a/kinode/src/register.rs b/kinode/src/register.rs index 6b4eb8a5..dfa39f28 100644 --- a/kinode/src/register.rs +++ b/kinode/src/register.rs @@ -68,8 +68,7 @@ pub async fn register( } // This is a **temporary** identity, passed to the UI. - // If it is confirmed through a /boot or /confirm-change-network-keys, - // then it will be used to replace the current identity. + // If it is confirmed through a /boot, then it will be used to replace the current identity. let our_temp_id = Arc::new(Identity { networking_key: format!("0x{}", public_key), name: "".to_string(), @@ -217,16 +216,6 @@ pub async fn register( login_provider, ) }), - )) - .or(warp::path("confirm-change-network-keys").and( - warp::post() - .and(warp::body::content_length_limit(1024 * 16)) - .and(warp::body::json()) - .and(tx) - .and(our_temp_id) - .and(net_keypair) - .and(keyfile) - .and_then(confirm_change_network_keys), )); let mut headers = HeaderMap::new(); @@ -574,72 +563,6 @@ async fn handle_login( success_response(sender, our, decoded_keyfile, encoded_keyfile).await } -async fn confirm_change_network_keys( - info: LoginAndResetInfo, - sender: Arc, - our: Arc, - networking_keypair: Arc>, - encoded_keyfile: Option>, -) -> Result { - if encoded_keyfile.is_none() { - return Ok(warp::reply::with_status( - warp::reply::json(&"Keyfile not present"), - StatusCode::NOT_FOUND, - ) - .into_response()); - } - let encoded_keyfile = encoded_keyfile.unwrap(); - let mut our = our.as_ref().clone(); - - // Get our name from our current keyfile - let old_decoded_keyfile = match keygen::decode_keyfile(&encoded_keyfile, &info.password_hash) { - Ok(k) => { - our.name = k.username.clone(); - k - } - Err(_) => { - return Ok(warp::reply::with_status( - warp::reply::json(&"Invalid password"), - StatusCode::UNAUTHORIZED, - ) - .into_response()); - } - }; - - // Determine if direct node or not - - if info.direct { - our.both_to_direct(); - } else { - our.both_to_routers(); - } - - let decoded_keyfile = Keyfile { - username: our.name.clone(), - routers: our.routers().unwrap_or(&vec![]).clone(), - networking_keypair: signature::Ed25519KeyPair::from_pkcs8(networking_keypair.as_ref()) - .unwrap(), - jwt_secret_bytes: old_decoded_keyfile.jwt_secret_bytes, - file_key: old_decoded_keyfile.file_key, - }; - - let encoded_keyfile = keygen::encode_keyfile( - info.password_hash, - decoded_keyfile.username.clone(), - decoded_keyfile.routers.clone(), - &networking_keypair, - &decoded_keyfile.jwt_secret_bytes, - &decoded_keyfile.file_key, - ); - - our.networking_key = format!( - "0x{}", - hex::encode(decoded_keyfile.networking_keypair.public_key().as_ref()) - ); - - success_response(sender, our, decoded_keyfile, encoded_keyfile).await -} - pub async fn assign_routing( our: &mut Identity, provider: Arc>, From f55da90800e1f0ed7a1e0a42f3efb744fbd48bef Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 11 Nov 2024 16:33:52 -0500 Subject: [PATCH 24/43] fix: rename build_packages to build-packages everywhere --- kinode/build.rs | 2 +- scripts/build-packages/src/main.rs | 2 +- scripts/build-release.py | 4 ++-- scripts/build-windows-artifact.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kinode/build.rs b/kinode/build.rs index 41279366..1f47750f 100644 --- a/kinode/build.rs +++ b/kinode/build.rs @@ -37,7 +37,7 @@ fn main() -> anyhow::Result<()> { p!("No path given via PATH_TO_PACKAGES_ZIP envvar. Defaulting to path of `kinode/target/packages.zip`."); CANONICAL_PACKAGES_ZIP_PATH.to_string() } else { - return Err(anyhow::anyhow!("You must build packages.zip with scripts/build_packages or set PATH_TO_PACKAGES_ZIP to point to your desired pacakges.zip (default path at kinode/target/packages.zip was not populated).")); + return Err(anyhow::anyhow!("You must build packages.zip with scripts/build-packages or set PATH_TO_PACKAGES_ZIP to point to your desired pacakges.zip (default path at kinode/target/packages.zip was not populated).")); } } }; diff --git a/scripts/build-packages/src/main.rs b/scripts/build-packages/src/main.rs index 59411f5f..2c50bfeb 100644 --- a/scripts/build-packages/src/main.rs +++ b/scripts/build-packages/src/main.rs @@ -75,7 +75,7 @@ fn build_and_zip_package( } fn main() -> anyhow::Result<()> { - let matches = Command::new("build_packages") + let matches = Command::new("build-packages") .about("Build the core Kinode packages.") .arg( Arg::new("FEATURES") diff --git a/scripts/build-release.py b/scripts/build-release.py index bd36ac1e..b602525e 100755 --- a/scripts/build-release.py +++ b/scripts/build-release.py @@ -33,7 +33,7 @@ def build_and_move(feature, tmp_dir, architecture, os_name): if feature: release_env["PATH_TO_PACKAGES_ZIP"] = f"../target/packages-{feature}.zip" subprocess.run( - ["cargo", "run", "-p", "build_packages", "--", "--features", feature], + ["cargo", "run", "-p", "build-packages", "--", "--features", feature], check=True, #stdout=subprocess.PIPE, #stderr=subprocess.PIPE, @@ -47,7 +47,7 @@ def build_and_move(feature, tmp_dir, architecture, os_name): ) zip_name = f"{zip_prefix}-{feature}.zip" else: - subprocess.run(["cargo", "run", "-p", "build_packages"], check=True) + subprocess.run(["cargo", "run", "-p", "build-packages"], check=True) subprocess.run( ["cargo", "build", "--release", "-p", "kinode"], check=True, diff --git a/scripts/build-windows-artifact.py b/scripts/build-windows-artifact.py index f60328af..34a4250f 100755 --- a/scripts/build-windows-artifact.py +++ b/scripts/build-windows-artifact.py @@ -68,7 +68,7 @@ def main(): subprocess.check_call([f'./{build_script_name}'], cwd=build_script_dir) # Run cargo build - subprocess.check_call(['cargo', 'build', '-p', 'build_packages'], cwd=repo_root) + subprocess.check_call(['cargo', 'build', '-p', 'build-packages'], cwd=repo_root) # Create the zip file output_zip = args.output From acb20c1db849c03e437b3efd880e71e894521974 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 11 Nov 2024 22:51:49 -0500 Subject: [PATCH 25/43] security: check structure of auth token before verifying --- kinode/src/http/utils.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/kinode/src/http/utils.rs b/kinode/src/http/utils.rs index ec3090e3..4e6d874c 100644 --- a/kinode/src/http/utils.rs +++ b/kinode/src/http/utils.rs @@ -20,20 +20,6 @@ pub struct RpcMessage { pub data: Option, } -/// Ingest an auth token given from client and return the node name or an error. -pub fn _verify_auth_token(auth_token: &str, jwt_secret: &[u8]) -> Result { - let Ok(secret) = Hmac::::new_from_slice(jwt_secret) else { - return Err(jwt::Error::Format); - }; - - let claims: Result = auth_token.verify_with_key(&secret); - - match claims { - Ok(data) => Ok(data.username), - Err(err) => Err(err), - } -} - pub fn auth_cookie_valid( our_node: &str, subdomain: Option<&ProcessId>, @@ -65,6 +51,13 @@ pub fn auth_cookie_valid( return false; }; + // Verify JWT structure (header.payload.signature) before attempting to decode + let jwt_format = + regex::Regex::new(r"^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$").unwrap(); + if !jwt_format.is_match(&auth_token) { + return false; + } + let claims: Result = auth_token.verify_with_key(&secret); match claims { From eba61d5d99f3d1b99ee7b1c225fc2348e9219a85 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 12 Nov 2024 13:53:48 -0800 Subject: [PATCH 26/43] docker: improve security; update README --- Dockerfile | 20 +++++++++++++++++++- README.md | 26 +++++++++++++++++++------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5496d4b2..0e5c68ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,9 +16,27 @@ FROM downloader_${TARGETARCH} AS downloader FROM debian:12-slim -RUN apt-get update && apt-get install openssl -y +# Create a non-root user and group +RUN groupadd -r kinode && \ + useradd -r -g kinode -d /kinode-home/home/kinode kinode + #useradd -r -g kinode -d /kinode-home/home/kinode -s /bin/false kinode + +RUN apt-get update && \ + apt-get install openssl -y && \ + rm -rf /var/lib/apt/lists/* + +# Create directory for kinode and set permissions +RUN mkdir -p /kinode-home/home/kinode && \ + chown -R kinode:kinode /kinode-home COPY --from=downloader /tmp/download/kinode /bin/kinode +RUN chown kinode:kinode /bin/kinode && \ + chmod 755 /bin/kinode + +# Switch to non-root user +USER kinode + +WORKDIR /kinode-home ENTRYPOINT [ "/bin/kinode" ] CMD [ "/kinode-home" ] diff --git a/README.md b/README.md index a28402d9..0c0d0dbd 100644 --- a/README.md +++ b/README.md @@ -202,20 +202,32 @@ To build a local Docker image, run the following command in this project root. ```bash # The `VERSION` may be replaced with the tag of a GitHub release +export VERSION=0.9.8 # Build for your system's architecture -docker build . -t 0xlynett/kinode --build-arg VERSION=v0.9.1 +docker build . -t kinode-${VERSION} --build-arg VERSION=v${VERSION} --platform linux/amd64 # Build a multiarch image -docker buildx build . --platform arm64,amd64 --build-arg VERSION=v0.9.1 -t 0xlynett/kinode +docker buildx build . -t kinode-${VERSION} --build-arg VERSION=v${VERSION} --platform arm64,amd64 ``` -For example: +To run, for example for a node named `helloworld.os`: ```bash -docker volume create kinode-volume +export NODENAME=helloworld.os -docker run -d -p 8080:8080 -it --name my-kinode \ - --mount type=volume,source=kinode-volume,destination=/kinode-home \ - 0xlynett/kinode +docker volume create kinode-${NODENAME} + +docker run -p 8080:8080 --rm -it --name kinode-${VERSION}-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} +``` + +which will launch your Kinode container attached to the terminal. +Alternatively you can run it detached: +``` +docker run -p 8080:8080 --rm -dt --name kinode-${VERSION}-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} +``` +Note that the `-t` flag *must* be passed. +If it is not passed, you must pass the `--detached` argument to the Kinode binary, i.e. +``` +docker run -p 8080:8080 --rm -d --name kinode-${VERSION}-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} /kinode-home --detached ``` From 5e1b9bd9a9950b0dc6a0e95f4581bb81be54a6e9 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 12 Nov 2024 13:59:29 -0800 Subject: [PATCH 27/43] docker: remove a commented-out line --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0e5c68ff..847343d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,6 @@ FROM debian:12-slim # Create a non-root user and group RUN groupadd -r kinode && \ useradd -r -g kinode -d /kinode-home/home/kinode kinode - #useradd -r -g kinode -d /kinode-home/home/kinode -s /bin/false kinode RUN apt-get update && \ apt-get install openssl -y && \ From d56846528278c3f9a1cc6be5f4367c6d939eb11f Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 12 Nov 2024 16:12:32 -0800 Subject: [PATCH 28/43] add some small fixes --- kinode/src/vfs.rs | 2 +- scripts/build-packages/src/main.rs | 6 +++--- scripts/build-release.py | 4 ++-- scripts/build-windows-artifact.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kinode/src/vfs.rs b/kinode/src/vfs.rs index 89125662..8ef7f53b 100644 --- a/kinode/src/vfs.rs +++ b/kinode/src/vfs.rs @@ -343,7 +343,7 @@ async fn handle_request( // current prepend to filepaths needs to be: /package_id/drive/path let (package_id, drive, rest) = parse_package_and_drive(&request.path, &vfs_path)?; - let drive = format!("{package_id}/{drive}"); + let drive = format!("/{package_id}/{drive}"); let action = request.action; let path = PathBuf::from(&request.path); diff --git a/scripts/build-packages/src/main.rs b/scripts/build-packages/src/main.rs index 59411f5f..b68ba9b4 100644 --- a/scripts/build-packages/src/main.rs +++ b/scripts/build-packages/src/main.rs @@ -75,7 +75,7 @@ fn build_and_zip_package( } fn main() -> anyhow::Result<()> { - let matches = Command::new("build_packages") + let matches = Command::new("build-packages") .about("Build the core Kinode packages.") .arg( Arg::new("FEATURES") @@ -97,8 +97,8 @@ fn main() -> anyhow::Result<()> { ) .get_matches(); - // kinode/target/debug/build_package - let current_exe_dir = std::env::current_exe() // build_package + // kinode/target/debug/build-package + let current_exe_dir = std::env::current_exe() // build-package .unwrap(); let top_level_dir = current_exe_dir .parent() // debug/ diff --git a/scripts/build-release.py b/scripts/build-release.py index bd36ac1e..b602525e 100755 --- a/scripts/build-release.py +++ b/scripts/build-release.py @@ -33,7 +33,7 @@ def build_and_move(feature, tmp_dir, architecture, os_name): if feature: release_env["PATH_TO_PACKAGES_ZIP"] = f"../target/packages-{feature}.zip" subprocess.run( - ["cargo", "run", "-p", "build_packages", "--", "--features", feature], + ["cargo", "run", "-p", "build-packages", "--", "--features", feature], check=True, #stdout=subprocess.PIPE, #stderr=subprocess.PIPE, @@ -47,7 +47,7 @@ def build_and_move(feature, tmp_dir, architecture, os_name): ) zip_name = f"{zip_prefix}-{feature}.zip" else: - subprocess.run(["cargo", "run", "-p", "build_packages"], check=True) + subprocess.run(["cargo", "run", "-p", "build-packages"], check=True) subprocess.run( ["cargo", "build", "--release", "-p", "kinode"], check=True, diff --git a/scripts/build-windows-artifact.py b/scripts/build-windows-artifact.py index f60328af..34a4250f 100755 --- a/scripts/build-windows-artifact.py +++ b/scripts/build-windows-artifact.py @@ -68,7 +68,7 @@ def main(): subprocess.check_call([f'./{build_script_name}'], cwd=build_script_dir) # Run cargo build - subprocess.check_call(['cargo', 'build', '-p', 'build_packages'], cwd=repo_root) + subprocess.check_call(['cargo', 'build', '-p', 'build-packages'], cwd=repo_root) # Create the zip file output_zip = args.output From 7f3d777fcaf321075156ebd22529a8a071c8d89f Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Wed, 13 Nov 2024 14:50:31 -0500 Subject: [PATCH 29/43] security: make sure to drop task for existing peer connection if we get a new handshake --- kinode/src/net/tcp/mod.rs | 25 +++++++++++++++---------- kinode/src/net/types.rs | 8 ++++++++ kinode/src/net/ws/mod.rs | 25 +++++++++++++++---------- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/kinode/src/net/tcp/mod.rs b/kinode/src/net/tcp/mod.rs index faeaf9b3..41f40eb0 100644 --- a/kinode/src/net/tcp/mod.rs +++ b/kinode/src/net/tcp/mod.rs @@ -207,12 +207,16 @@ async fn recv_connection( &their_id, )?; - let (peer, peer_rx) = Peer::new(their_id.clone(), their_handshake.proxy_request); - data.peers.insert(their_id.name.clone(), peer).await; + // if we already have a connection to this peer, kill it so we + // don't build a duplicate connection + if let Some(mut peer) = data.peers.get_mut(&their_handshake.name) { + peer.kill(); + } - tokio::spawn(utils::maintain_connection( + let (mut peer, peer_rx) = Peer::new(their_id.clone(), their_handshake.proxy_request); + peer.handle = Some(tokio::spawn(utils::maintain_connection( their_handshake.name, - data.peers, + data.peers.clone(), PeerConnection { noise: noise.into_transport_mode()?, buf, @@ -221,7 +225,8 @@ async fn recv_connection( peer_rx, ext.kernel_message_tx, ext.print_tx, - )); + ))); + data.peers.insert(their_id.name.clone(), peer).await; Ok(()) } @@ -322,17 +327,17 @@ pub async fn recv_via_router( }; match connect_with_handshake_via_router(&ext, &peer_id, &router_id, stream).await { Ok(connection) => { - let (peer, peer_rx) = Peer::new(peer_id.clone(), false); - data.peers.insert(peer_id.name.clone(), peer).await; // maintain direct connection - tokio::spawn(utils::maintain_connection( - peer_id.name, + let (mut peer, peer_rx) = Peer::new(peer_id.clone(), false); + peer.handle = Some(tokio::spawn(utils::maintain_connection( + peer_id.name.clone(), data.peers.clone(), connection, peer_rx, ext.kernel_message_tx, ext.print_tx, - )); + ))); + data.peers.insert(peer_id.name, peer).await; } Err(e) => { print_debug(&ext.print_tx, &format!("net: error getting routed: {e}")).await; diff --git a/kinode/src/net/types.rs b/kinode/src/net/types.rs index 7b37d918..669393a9 100644 --- a/kinode/src/net/types.rs +++ b/kinode/src/net/types.rs @@ -175,6 +175,7 @@ pub struct Peer { /// associated with them. We can send them prompts to establish Passthroughs. pub routing_for: bool, pub sender: UnboundedSender, + pub handle: Option>, /// unix timestamp of last message sent *or* received pub last_message: u64, } @@ -189,6 +190,7 @@ impl Peer { identity, routing_for, sender: peer_tx, + handle: None, last_message: std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() @@ -215,6 +217,12 @@ impl Peer { .unwrap() .as_secs() } + + pub fn kill(&mut self) { + if let Some(handle) = self.handle.take() { + handle.abort(); + } + } } /// [`Identity`], with additional fields for networking. #[derive(Clone)] diff --git a/kinode/src/net/ws/mod.rs b/kinode/src/net/ws/mod.rs index 0e2b9714..11a01077 100644 --- a/kinode/src/net/ws/mod.rs +++ b/kinode/src/net/ws/mod.rs @@ -187,17 +187,17 @@ pub async fn recv_via_router( }; match connect_with_handshake_via_router(&ext, &peer_id, &router_id, socket).await { Ok(connection) => { - let (peer, peer_rx) = Peer::new(peer_id.clone(), false); - data.peers.insert(peer_id.name.clone(), peer).await; // maintain direct connection - tokio::spawn(utils::maintain_connection( - peer_id.name, + let (mut peer, peer_rx) = Peer::new(peer_id.clone(), false); + peer.handle = Some(tokio::spawn(utils::maintain_connection( + peer_id.name.clone(), data.peers.clone(), connection, peer_rx, ext.kernel_message_tx, ext.print_tx, - )); + ))); + data.peers.insert(peer_id.name, peer).await; } Err(e) => { print_debug(&ext.print_tx, &format!("net: error getting routed: {e}")).await; @@ -263,12 +263,16 @@ async fn recv_connection( &their_id, )?; - let (peer, peer_rx) = Peer::new(their_id.clone(), their_handshake.proxy_request); - data.peers.insert(their_id.name.clone(), peer).await; + // if we already have a connection to this peer, kill it so we + // don't build a duplicate connection + if let Some(mut peer) = data.peers.get_mut(&their_handshake.name) { + peer.kill(); + } - tokio::spawn(utils::maintain_connection( + let (mut peer, peer_rx) = Peer::new(their_id.clone(), their_handshake.proxy_request); + peer.handle = Some(tokio::spawn(utils::maintain_connection( their_handshake.name, - data.peers, + data.peers.clone(), PeerConnection { noise: noise.into_transport_mode()?, buf, @@ -277,7 +281,8 @@ async fn recv_connection( peer_rx, ext.kernel_message_tx, ext.print_tx, - )); + ))); + data.peers.insert(their_id.name.clone(), peer).await; Ok(()) } From 86a5fe382a2a70faf91b4d4b037b5a2d4a178fc2 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Wed, 13 Nov 2024 14:58:54 -0500 Subject: [PATCH 30/43] security: add max open websockets, reject incoming if reached --- kinode/src/http/server.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index 37f14ed0..a3259f94 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -30,6 +30,8 @@ const HTTP_SELF_IMPOSED_TIMEOUT: u64 = 15; #[cfg(feature = "simulation-mode")] const HTTP_SELF_IMPOSED_TIMEOUT: u64 = 600; +const WS_SELF_IMPOSED_MAX_CONNECTIONS: u32 = 128; + const LOGIN_HTML: &str = include_str!("login.html"); /// mapping from a given HTTP request (assigned an ID) to the oneshot @@ -402,6 +404,19 @@ async fn ws_handler( .send(&print_tx) .await; + if ws_senders.len() >= WS_SELF_IMPOSED_MAX_CONNECTIONS { + Printout::new( + 0, + format!( + "http-server: too many open websockets ({})! rejecting incoming", + ws_senders.len() + ), + ) + .send(&print_tx) + .await; + return Err(warp::reject::reject()); + } + let serialized_headers = utils::serialize_headers(&headers); let ws_path_bindings = ws_path_bindings.read().await; From 75943623655450c7a02a9c8eac98fa0ee1185e34 Mon Sep 17 00:00:00 2001 From: "nick.kino" <79381743+nick1udwig@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:59:50 -0800 Subject: [PATCH 31/43] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0c0d0dbd..a6ffd4d0 100644 --- a/README.md +++ b/README.md @@ -218,16 +218,16 @@ export NODENAME=helloworld.os docker volume create kinode-${NODENAME} -docker run -p 8080:8080 --rm -it --name kinode-${VERSION}-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} +docker run -p 8080:8080 --rm -it --name kinode-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} ``` which will launch your Kinode container attached to the terminal. Alternatively you can run it detached: ``` -docker run -p 8080:8080 --rm -dt --name kinode-${VERSION}-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} +docker run -p 8080:8080 --rm -dt --name kinode-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} ``` Note that the `-t` flag *must* be passed. If it is not passed, you must pass the `--detached` argument to the Kinode binary, i.e. ``` -docker run -p 8080:8080 --rm -d --name kinode-${VERSION}-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} /kinode-home --detached +docker run -p 8080:8080 --rm -d --name kinode-${NODENAME} --mount type=volume,source=kinode-${NODENAME},destination=/kinode-home kinode-${VERSION} /kinode-home --detached ``` From d23fb78c76a5b6fddeebe82f150e71fc696685a8 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Fri, 15 Nov 2024 17:05:07 -0500 Subject: [PATCH 32/43] fix error and warning, remove dead code --- kinode/src/http/server.rs | 2 +- kinode/src/kernel/mod.rs | 2 +- kinode/src/kernel/process.rs | 2 +- kinode/src/register.rs | 3 +-- lib/src/core.rs | 6 ------ 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index a3259f94..dd230099 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -404,7 +404,7 @@ async fn ws_handler( .send(&print_tx) .await; - if ws_senders.len() >= WS_SELF_IMPOSED_MAX_CONNECTIONS { + if ws_senders.len() >= WS_SELF_IMPOSED_MAX_CONNECTIONS as usize { Printout::new( 0, format!( diff --git a/kinode/src/kernel/mod.rs b/kinode/src/kernel/mod.rs index 6b176b90..4f7a4658 100644 --- a/kinode/src/kernel/mod.rs +++ b/kinode/src/kernel/mod.rs @@ -56,7 +56,7 @@ pub struct RestartBackoff { /// how many times has process tried to restart in a row consecutive_attempts: u32, /// task that will do the restart after wait time has elapsed - restart_handle: Option>, + _restart_handle: Option>, } /// persist kernel's process_map state for next bootup diff --git a/kinode/src/kernel/process.rs b/kinode/src/kernel/process.rs index 375fa3ac..94aa8ea9 100644 --- a/kinode/src/kernel/process.rs +++ b/kinode/src/kernel/process.rs @@ -515,7 +515,7 @@ pub async fn make_process_loop( *restart_backoff_lock = Some(RestartBackoff { next_soonest_restart_time, consecutive_attempts, - restart_handle, + _restart_handle: restart_handle, }); } // if requests, fire them diff --git a/kinode/src/register.rs b/kinode/src/register.rs index dfa39f28..8c9d898c 100644 --- a/kinode/src/register.rs +++ b/kinode/src/register.rs @@ -9,8 +9,7 @@ use alloy_primitives::{Address as EthAddress, Bytes, FixedBytes, U256}; use alloy_sol_types::{eip712_domain, SolCall, SolStruct}; use base64::{engine::general_purpose::STANDARD as base64_standard, Engine}; use lib::types::core::{ - BootInfo, Identity, ImportKeyfileInfo, Keyfile, LoginAndResetInfo, LoginInfo, NodeRouting, - UnencryptedIdentity, + BootInfo, Identity, ImportKeyfileInfo, Keyfile, LoginInfo, NodeRouting, UnencryptedIdentity, }; use ring::{rand::SystemRandom, signature, signature::KeyPair}; use std::{ diff --git a/lib/src/core.rs b/lib/src/core.rs index e27b26ea..c6d80bb9 100644 --- a/lib/src/core.rs +++ b/lib/src/core.rs @@ -1085,12 +1085,6 @@ pub struct LoginInfo { pub subdomain: Option, } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct LoginAndResetInfo { - pub password_hash: String, - pub direct: bool, -} - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Identity { pub name: NodeId, From 51189927068414514dfd573b4b17cde94f23c0dc Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Fri, 15 Nov 2024 17:18:49 -0500 Subject: [PATCH 33/43] sanitize subdomain, make cookie secure --- kinode/src/http/server.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index dd230099..7680cb6f 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -363,12 +363,28 @@ async fn login_handler( let cookie = match info.subdomain.unwrap_or_default().as_str() { "" => format!("kinode-auth_{our}={token};"), - subdomain => format!("kinode-auth_{our}@{subdomain}={token};"), + subdomain => { + // enforce that subdomain string only contains a-z, 0-9, and - + let subdomain = subdomain + .chars() + .filter(|c| c.is_ascii_alphanumeric() || c == &'-') + .collect::(); + format!("kinode-auth_{our}@{subdomain}={token};") + } }; match HeaderValue::from_str(&cookie) { Ok(v) => { response.headers_mut().append("set-cookie", v); + response + .headers_mut() + .append("HttpOnly", HeaderValue::from_static("true")); + response + .headers_mut() + .append("Secure", HeaderValue::from_static("true")); + response + .headers_mut() + .append("SameSite", HeaderValue::from_static("Strict")); Ok(response) } Err(e) => Ok(warp::reply::with_status( From 9fd143bfeb181c922b6aed72408f24a072702d9f Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Tue, 19 Nov 2024 16:04:24 -0500 Subject: [PATCH 34/43] security: switch password hashing to Argon2 -- error shown in JS is "fake", using argon2-browser from CDN --- Cargo.lock | 30 ++++- css/kinode.css | 4 +- kinode/Cargo.toml | 1 + kinode/src/http/login.html | 45 +++++--- kinode/src/keygen.rs | 4 +- kinode/src/main.rs | 24 ++-- kinode/src/register-ui/index.html | 3 + kinode/src/register-ui/package-lock.json | 6 + kinode/src/register-ui/package.json | 3 +- .../register-ui/src/pages/ImportKeyfile.tsx | 40 +++---- kinode/src/register-ui/src/pages/Login.tsx | 15 +-- .../src/register-ui/src/pages/SetPassword.tsx | 107 +++++++++--------- kinode/src/register.rs | 4 +- 13 files changed, 169 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0d26c72..97286cb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -1058,6 +1058,18 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures", + "password-hash 0.5.0", +] + [[package]] name = "ark-ff" version = "0.3.0" @@ -3721,6 +3733,7 @@ dependencies = [ "alloy-sol-macro", "alloy-sol-types", "anyhow", + "argon2", "async-trait", "base64 0.22.1", "bincode", @@ -4562,6 +4575,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" @@ -4582,7 +4606,7 @@ checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest 0.10.7", "hmac", - "password-hash", + "password-hash 0.4.2", "sha2", ] @@ -5794,7 +5818,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "snow" version = "0.9.0" -source = "git+https://github.com/dr-frmr/snow?branch=dr/extract_cipherstates#1d4eb5f6747aa59aabb32bbbe698fb4bb7dfb9a4" +source = "git+https://github.com/dr-frmr/snow?branch=dr%2Fextract_cipherstates#1d4eb5f6747aa59aabb32bbbe698fb4bb7dfb9a4" dependencies = [ "aes-gcm", "blake2", diff --git a/css/kinode.css b/css/kinode.css index b554c30f..276978ef 100644 --- a/css/kinode.css +++ b/css/kinode.css @@ -1,3 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Kode+Mono:wght@700&display=swap'); + /* CSS Reset and Base Styles */ *, *::before, @@ -23,8 +25,6 @@ select { font-family: var(--font-family-main); } -@import url('https://fonts.googleapis.com/css2?family=Kode+Mono:wght@700&display=swap'); - /* Variables */ :root { color-scheme: light dark; diff --git a/kinode/Cargo.toml b/kinode/Cargo.toml index b1240fc5..8773d9a6 100644 --- a/kinode/Cargo.toml +++ b/kinode/Cargo.toml @@ -41,6 +41,7 @@ alloy-primitives = "0.7.6" alloy-sol-macro = "0.7.6" alloy-sol-types = "0.7.6" anyhow = "1.0.71" +argon2 = "0.5.3" async-trait = "0.1.71" base64 = "0.22.0" bincode = "1.3.3" diff --git a/kinode/src/http/login.html b/kinode/src/http/login.html index 87106883..59f22746 100644 --- a/kinode/src/http/login.html +++ b/kinode/src/http/login.html @@ -153,8 +153,9 @@
- - + diff --git a/kinode/src/register-ui/package-lock.json b/kinode/src/register-ui/package-lock.json index ed73a839..4234ce91 100644 --- a/kinode/src/register-ui/package-lock.json +++ b/kinode/src/register-ui/package-lock.json @@ -12,6 +12,7 @@ "@rainbow-me/rainbowkit": "^2.1.6", "@szhsin/react-menu": "^4.1.0", "@tanstack/react-query": "^5.45.1", + "argon2-browser": "^1.18.0", "idna-uts46-hx": "^6.0.4", "is-valid-domain": "^0.1.6", "jazzicon": "^1.5.0", @@ -6390,6 +6391,11 @@ "dev": true, "license": "MIT" }, + "node_modules/argon2-browser": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz", + "integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", diff --git a/kinode/src/register-ui/package.json b/kinode/src/register-ui/package.json index 7dd85af4..56ce58c7 100644 --- a/kinode/src/register-ui/package.json +++ b/kinode/src/register-ui/package.json @@ -8,6 +8,7 @@ "@rainbow-me/rainbowkit": "^2.1.6", "@szhsin/react-menu": "^4.1.0", "@tanstack/react-query": "^5.45.1", + "argon2-browser": "^1.18.0", "idna-uts46-hx": "^6.0.4", "is-valid-domain": "^0.1.6", "jazzicon": "^1.5.0", @@ -60,4 +61,4 @@ "vite": "^5.2.10" }, "type": "module" -} \ No newline at end of file +} diff --git a/kinode/src/register-ui/src/pages/ImportKeyfile.tsx b/kinode/src/register-ui/src/pages/ImportKeyfile.tsx index ff1d6070..c633a508 100644 --- a/kinode/src/register-ui/src/pages/ImportKeyfile.tsx +++ b/kinode/src/register-ui/src/pages/ImportKeyfile.tsx @@ -6,7 +6,6 @@ import { } from "react"; import { PageProps } from "../lib/types"; import Loader from "../components/Loader"; -import { sha256, toBytes } from "viem"; import { redirectToHomepage } from "../utils/redirect-to-homepage"; interface ImportKeyfileProps extends PageProps { } @@ -56,27 +55,30 @@ function ImportKeyfile({ try { if (keyErrs.length === 0 && localKey !== null) { - let salted = [knsName, pw].join(""); - let hashed_password = sha256(toBytes(salted)); + argon2.hash({ pass: pw, salt: knsName, hashLen: 32, time: 2, mem: 19456, type: argon2.ArgonType.Argon2id }).then(async h => { + const hashed_password_hex = `0x${h.hashHex}`; - const result = await fetch("/import-keyfile", { - method: "POST", - credentials: 'include', - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - keyfile: Buffer.from(localKey).toString('utf8'), - password_hash: hashed_password, - }), + const result = await fetch("/import-keyfile", { + method: "POST", + credentials: 'include', + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + keyfile: Buffer.from(localKey).toString('utf8'), + password_hash: hashed_password_hex, + }), + }); + + if (result.status > 399) { + throw new Error(await result.text()); + } + redirectToHomepage(); + }).catch(err => { + window.alert(String(err)); + setLoading(false); }); - - if (result.status > 399) { - throw new Error("Incorrect password"); - } - redirectToHomepage(); - } - } catch { - window.alert("An error occurred, please try again."); + } catch (err) { + window.alert(String(err)); setLoading(false); } }, diff --git a/kinode/src/register-ui/src/pages/Login.tsx b/kinode/src/register-ui/src/pages/Login.tsx index a0c19970..e8ec1d39 100644 --- a/kinode/src/register-ui/src/pages/Login.tsx +++ b/kinode/src/register-ui/src/pages/Login.tsx @@ -2,7 +2,6 @@ import { FormEvent, useCallback, useEffect, useState } from "react"; import { PageProps, UnencryptedIdentity } from "../lib/types"; import Loader from "../components/Loader"; import { useNavigate } from "react-router-dom"; -import { sha256, toBytes } from "viem"; import { Tooltip } from "../components/Tooltip"; import { redirectToHomepage } from "../utils/redirect-to-homepage"; @@ -40,10 +39,9 @@ function Login({ e?.preventDefault(); e?.stopPropagation(); - try { - setLoading("Logging in..."); - let salted = [knsName, pw].join(""); - let hashed_password = sha256(toBytes(salted)); + setLoading("Logging in..."); + argon2.hash({ pass: pw, salt: knsName, hashLen: 32, time: 2, mem: 19456, type: argon2.ArgonType.Argon2id }).then(async h => { + const hashed_password_hex = `0x${h.hashHex}`; const result = await fetch( "/login", @@ -51,7 +49,7 @@ function Login({ method: "POST", credentials: 'include', headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ password_hash: hashed_password }), + body: JSON.stringify({ password_hash: hashed_password_hex }), } ); @@ -59,11 +57,10 @@ function Login({ throw new Error(await result.text()); } redirectToHomepage(); - - } catch (err: any) { + }).catch(err => { setKeyErrs([String(err)]); setLoading(""); - } + }); }, [pw] ); diff --git a/kinode/src/register-ui/src/pages/SetPassword.tsx b/kinode/src/register-ui/src/pages/SetPassword.tsx index 6ad7660d..cc6c86f1 100644 --- a/kinode/src/register-ui/src/pages/SetPassword.tsx +++ b/kinode/src/register-ui/src/pages/SetPassword.tsx @@ -2,7 +2,6 @@ import React, { useState, useEffect, FormEvent, useCallback } from "react"; import Loader from "../components/Loader"; import { downloadKeyfile } from "../utils/download-keyfile"; import { Tooltip } from "../components/Tooltip"; -import { sha256, toBytes } from "viem"; import { useSignTypedData, useAccount, useChainId } from 'wagmi' import { KIMAP } from "../abis"; import { redirectToHomepage } from "../utils/redirect-to-homepage"; @@ -51,64 +50,68 @@ function SetPassword({ setTimeout(async () => { setLoading(true); - let salted = [knsName, pw].join(""); - let hashed_password = sha256(toBytes(salted)); - let owner = address; - let timestamp = Date.now(); + argon2.hash({ pass: pw, salt: knsName, hashLen: 32, time: 2, mem: 19456, type: argon2.ArgonType.Argon2id }).then(async h => { + const hashed_password_hex = `0x${h.hashHex}` as `0x${string}`; + let owner = address; + let timestamp = Date.now(); - const signature = await signTypedDataAsync({ - domain: { - name: "Kimap", - version: "1", - chainId: chainId, - verifyingContract: KIMAP, - }, - types: { - Boot: [ - { name: 'username', type: 'string' }, - { name: 'password_hash', type: 'bytes32' }, - { name: 'timestamp', type: 'uint256' }, - { name: 'direct', type: 'bool' }, - { name: 'reset', type: 'bool' }, - { name: 'chain_id', type: 'uint256' }, - ], - }, - primaryType: 'Boot', - message: { - username: knsName, - password_hash: hashed_password, - timestamp: BigInt(timestamp), - direct, - reset, - chain_id: BigInt(chainId), - }, - }) - - try { - const result = await fetch("/boot", { - method: "POST", - headers: { "Content-Type": "application/json" }, - credentials: "include", - body: JSON.stringify({ - password_hash: hashed_password, - reset, + const signature = await signTypedDataAsync({ + domain: { + name: "Kimap", + version: "1", + chainId: chainId, + verifyingContract: KIMAP, + }, + types: { + Boot: [ + { name: 'username', type: 'string' }, + { name: 'password_hash', type: 'bytes32' }, + { name: 'timestamp', type: 'uint256' }, + { name: 'direct', type: 'bool' }, + { name: 'reset', type: 'bool' }, + { name: 'chain_id', type: 'uint256' }, + ], + }, + primaryType: 'Boot', + message: { username: knsName, + password_hash: hashed_password_hex, + timestamp: BigInt(timestamp), direct, - owner, - timestamp, - signature, - chain_id: chainId, - }), + reset, + chain_id: BigInt(chainId), + }, }); - const base64String = await result.json(); - downloadKeyfile(knsName, base64String); - redirectToHomepage(); + try { + const result = await fetch("/boot", { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify({ + password_hash: hashed_password_hex, + reset, + username: knsName, + direct, + owner, + timestamp, + signature, + chain_id: chainId, + }), + }); + const base64String = await result.json(); - } catch { - alert("There was an error setting your password, please try again."); + downloadKeyfile(knsName, base64String); + redirectToHomepage(); + + } catch { + alert("There was an error setting your password, please try again."); + setLoading(false); + } + }).catch(err => { + alert(String(err)); setLoading(false); - } + }); }, 500); }, [direct, pw, pw2, reset, knsName] diff --git a/kinode/src/register.rs b/kinode/src/register.rs index 8c9d898c..ac59c056 100644 --- a/kinode/src/register.rs +++ b/kinode/src/register.rs @@ -483,7 +483,7 @@ async fn handle_import_keyfile( } Err(_) => { return Ok(warp::reply::with_status( - warp::reply::json(&"Incorrect password_hash".to_string()), + warp::reply::json(&"Incorrect password!".to_string()), StatusCode::UNAUTHORIZED, ) .into_response()) @@ -543,7 +543,7 @@ async fn handle_login( } Err(_) => { return Ok(warp::reply::with_status( - warp::reply::json(&"Incorrect password_hash"), + warp::reply::json(&"Incorrect password!"), StatusCode::UNAUTHORIZED, ) .into_response()) From aed5758ed9e95602b2087187a4ceba06d1d495d4 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 19 Nov 2024 18:04:06 -0800 Subject: [PATCH 35/43] kernel: dont replace `last_blob` with None --- kinode/src/kernel/standard_host.rs | 15 ++++++++++++--- kinode/src/kernel/standard_host_v0.rs | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/kinode/src/kernel/standard_host.rs b/kinode/src/kernel/standard_host.rs index fc567b9c..ce5d3c3e 100644 --- a/kinode/src/kernel/standard_host.rs +++ b/kinode/src/kernel/standard_host.rs @@ -99,7 +99,10 @@ impl process::ProcessState { ref expects_response, .. }) => { - self.last_blob = km.lazy_load_blob; + if km.lazy_load_blob.is_some() { + self.last_blob = km.lazy_load_blob; + km.lazy_load_blob = None; + } km.lazy_load_blob = None; if expects_response.is_some() || km.rsvp.is_some() { // update prompting_message iff there is someone to reply to @@ -109,13 +112,19 @@ impl process::ProcessState { } t::Message::Response(_) => match self.contexts.remove(&km.id) { Some((context, _timeout_handle)) => { - self.last_blob = km.lazy_load_blob; + if km.lazy_load_blob.is_some() { + self.last_blob = km.lazy_load_blob; + km.lazy_load_blob = None; + } km.lazy_load_blob = None; self.prompting_message = context.prompting_message; (km, context.context) } None => { - self.last_blob = km.lazy_load_blob; + if km.lazy_load_blob.is_some() { + self.last_blob = km.lazy_load_blob; + km.lazy_load_blob = None; + } km.lazy_load_blob = None; self.prompting_message = Some(km.clone()); (km, None) diff --git a/kinode/src/kernel/standard_host_v0.rs b/kinode/src/kernel/standard_host_v0.rs index 987f4f46..dfc8f12c 100644 --- a/kinode/src/kernel/standard_host_v0.rs +++ b/kinode/src/kernel/standard_host_v0.rs @@ -103,8 +103,10 @@ impl process::ProcessState { ref expects_response, .. }) => { - self.last_blob = km.lazy_load_blob; - km.lazy_load_blob = None; + if km.lazy_load_blob.is_some() { + self.last_blob = km.lazy_load_blob; + km.lazy_load_blob = None; + } if expects_response.is_some() || km.rsvp.is_some() { // update prompting_message iff there is someone to reply to self.prompting_message = Some(km.clone()); @@ -113,14 +115,18 @@ impl process::ProcessState { } t::Message::Response(_) => match self.contexts.remove(&km.id) { Some((context, _timeout_handle)) => { - self.last_blob = km.lazy_load_blob; - km.lazy_load_blob = None; + if km.lazy_load_blob.is_some() { + self.last_blob = km.lazy_load_blob; + km.lazy_load_blob = None; + } self.prompting_message = context.prompting_message; (km, context.context) } None => { - self.last_blob = km.lazy_load_blob; - km.lazy_load_blob = None; + if km.lazy_load_blob.is_some() { + self.last_blob = km.lazy_load_blob; + km.lazy_load_blob = None; + } self.prompting_message = Some(km.clone()); (km, None) } From dec8e927b5d4a1eb1b1ffb866ef0fd45ec344d16 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:41:53 +0000 Subject: [PATCH 36/43] Format Rust code using rustfmt --- kinode/src/http/server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index 644e5cdf..5113b54e 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -416,7 +416,7 @@ async fn login_handler( .headers_mut() .append("Content-Length", HeaderValue::from_str("0").unwrap()); } - + Ok(response) } Err(e) => Ok(warp::reply::with_status( From a780a575ff34ad54d901d5fe3763719bf6b4b914 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Mon, 2 Dec 2024 14:37:04 -0800 Subject: [PATCH 37/43] remove WsRegister `encrypted` field --- lib/src/http/server_types.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/src/http/server_types.rs b/lib/src/http/server_types.rs index 1ed5d2a9..9b1ec87b 100644 --- a/lib/src/http/server_types.rs +++ b/lib/src/http/server_types.rs @@ -184,21 +184,17 @@ pub enum HttpServerError { } /// Structure sent from client websocket to this server upon opening a new connection. -/// After this is sent, depending on the `encrypted` flag, the channel will either be -/// open to send and receive plaintext messages or messages encrypted with a symmetric -/// key derived from the JWT. +/// After this is sent the channel will be open to send and receive plaintext messages. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct WsRegister { pub auth_token: String, pub target_process: String, - pub encrypted: bool, // TODO symmetric key exchange here if true } /// Structure sent from this server to client websocket upon opening a new connection. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct WsRegisterResponse { pub channel_id: u32, - // TODO symmetric key exchange here } #[derive(Debug, Serialize, Deserialize)] From 12f4507c2147e34d0c8114370201e35176adfbe0 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Mon, 2 Dec 2024 18:32:11 -0500 Subject: [PATCH 38/43] security: always send JWT cookie with proper headers, make JWT expire --- kinode/src/http/server.rs | 19 ++++++++++--------- kinode/src/http/utils.rs | 20 ++++++++++++-------- kinode/src/keygen.rs | 8 +++++++- kinode/src/register.rs | 9 +++++++++ 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index 5113b54e..cb69db55 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -15,12 +15,13 @@ use lib::types::core::{ }; use route_recognizer::Router; use sha2::{Digest, Sha256}; -use std::collections::HashMap; -use std::net::SocketAddr; -use std::sync::Arc; +use std::{collections::HashMap, net::SocketAddr, sync::Arc}; use tokio::sync::RwLock; use warp::{ - http::{header::HeaderValue, StatusCode}, + http::{ + header::{HeaderValue, SET_COOKIE}, + StatusCode, + }, ws::{WebSocket, Ws}, Filter, Reply, }; @@ -386,7 +387,7 @@ async fn login_handler( match HeaderValue::from_str(&cookie) { Ok(v) => { - response.headers_mut().append("set-cookie", v); + response.headers_mut().append(SET_COOKIE, v); response .headers_mut() .append("HttpOnly", HeaderValue::from_static("true")); @@ -491,12 +492,12 @@ async fn ws_handler( // parse out subdomain from host (there can only be one) let request_subdomain = host.host().split('.').next().unwrap_or(""); if request_subdomain != subdomain - || !utils::auth_cookie_valid(&our, Some(&app), auth_token, &jwt_secret_bytes) + || !utils::auth_token_valid(&our, Some(&app), auth_token, &jwt_secret_bytes) { return Err(warp::reject::not_found()); } } else { - if !utils::auth_cookie_valid(&our, None, auth_token, &jwt_secret_bytes) { + if !utils::auth_token_valid(&our, None, auth_token, &jwt_secret_bytes) { return Err(warp::reject::not_found()); } } @@ -631,7 +632,7 @@ async fn http_handler( .body(vec![]) .into_response()); } - if !utils::auth_cookie_valid( + if !utils::auth_token_valid( &our, Some(&app), serialized_headers.get("cookie").unwrap_or(&"".to_string()), @@ -644,7 +645,7 @@ async fn http_handler( .into_response()); } } else { - if !utils::auth_cookie_valid( + if !utils::auth_token_valid( &our, None, serialized_headers.get("cookie").unwrap_or(&"".to_string()), diff --git a/kinode/src/http/utils.rs b/kinode/src/http/utils.rs index 4e6d874c..642e5da2 100644 --- a/kinode/src/http/utils.rs +++ b/kinode/src/http/utils.rs @@ -20,13 +20,13 @@ pub struct RpcMessage { pub data: Option, } -pub fn auth_cookie_valid( +pub fn auth_token_valid( our_node: &str, subdomain: Option<&ProcessId>, - cookie: &str, + auth_token: &str, jwt_secret: &[u8], ) -> bool { - let cookie: Vec<&str> = cookie.split("; ").collect(); + let token: Vec<&str> = auth_token.split("; ").collect(); let token_label = match subdomain { None => format!("kinode-auth_{our_node}"), @@ -34,10 +34,10 @@ pub fn auth_cookie_valid( }; let mut auth_token = None; - for entry in cookie { - let cookie_parts: Vec<&str> = entry.split('=').collect(); - if cookie_parts.len() == 2 && cookie_parts[0] == token_label { - auth_token = Some(cookie_parts[1].to_string()); + for entry in token { + let token_parts: Vec<&str> = entry.split('=').collect(); + if token_parts.len() == 2 && token_parts[0] == token_label { + auth_token = Some(token_parts[1].to_string()); break; } } @@ -61,7 +61,11 @@ pub fn auth_cookie_valid( let claims: Result = auth_token.verify_with_key(&secret); match claims { - Ok(data) => data.username == our_node && data.subdomain == subdomain.map(|s| s.to_string()), + Ok(data) => { + data.username == our_node + && data.subdomain == subdomain.map(|s| s.to_string()) + && data.expiration > chrono::Utc::now().timestamp() as u64 + } Err(_) => false, } } diff --git a/kinode/src/keygen.rs b/kinode/src/keygen.rs index 4fc1963b..f6bbb330 100644 --- a/kinode/src/keygen.rs +++ b/kinode/src/keygen.rs @@ -11,6 +11,7 @@ use ring::signature::{self, KeyPair}; use std::{ net::{IpAddr, Ipv4Addr, Ipv6Addr}, num::NonZeroU32, + ops::Add, }; type DiskKey = [u8; CREDENTIAL_LEN]; @@ -134,10 +135,15 @@ pub fn generate_jwt( subdomain => Some(subdomain.to_string()), }; + // set JWT to expire in 6 months + let expiration = chrono::Utc::now() + .add(chrono::Duration::weeks(26)) + .timestamp() as u64; + let claims = crate::http::server_types::JwtClaims { username: username.to_string(), subdomain, - expiration: 0, + expiration, }; claims.sign_with_key(&jwt_secret).ok() diff --git a/kinode/src/register.rs b/kinode/src/register.rs index ac59c056..3be3749b 100644 --- a/kinode/src/register.rs +++ b/kinode/src/register.rs @@ -695,6 +695,15 @@ async fn success_response( match HeaderValue::from_str(&format!("kinode-auth_{}={token};", our.name)) { Ok(v) => { response.headers_mut().append(SET_COOKIE, v); + response + .headers_mut() + .append("HttpOnly", HeaderValue::from_static("true")); + response + .headers_mut() + .append("Secure", HeaderValue::from_static("true")); + response + .headers_mut() + .append("SameSite", HeaderValue::from_static("Strict")); } Err(_) => { return Ok(warp::reply::with_status( From 8200ecb6a73adffe8a044b26b9a68f86f3901802 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Mon, 2 Dec 2024 16:19:06 -0800 Subject: [PATCH 39/43] improve robustness of runtime build (esp w kit) --- kinode/build.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/kinode/build.rs b/kinode/build.rs index 41279366..b5d8b8be 100644 --- a/kinode/build.rs +++ b/kinode/build.rs @@ -30,7 +30,23 @@ fn compute_hash(file_path: &Path) -> anyhow::Result { fn main() -> anyhow::Result<()> { let path_to_packages_zip = match std::env::var("PATH_TO_PACKAGES_ZIP") { - Ok(env_var) => env_var, + Ok(env_var) => { + let path = PathBuf::from(&env_var); + if !path.exists() { + let path = std::env::current_dir()?; + let Some(path) = path.parent() else { + return Err(anyhow::anyhow!("Given path to packages {env_var} not found (cwd: {:?})", std::env::current_dir())); + }; + let path = path.join(&env_var); + if path.exists() { + path.display().to_string() + } else { + return Err(anyhow::anyhow!("Given path to packages {env_var} not found in parent of cwd: {:?}", std::env::current_dir())); + } + } else { + env_var + } + } Err(_) => { let canonical_path = PathBuf::from(CANONICAL_PACKAGES_ZIP_PATH); if canonical_path.exists() { @@ -49,6 +65,10 @@ fn main() -> anyhow::Result<()> { } let path_to_packages_zip_path = PathBuf::from(&path_to_packages_zip).canonicalize()?; + let canonical_packages_zip_path = PathBuf::from(CANONICAL_PACKAGES_ZIP_PATH); + if !canonical_packages_zip_path.exists() { + std::fs::File::create(&canonical_packages_zip_path)?; + } let canonical_packages_zip_path = PathBuf::from(CANONICAL_PACKAGES_ZIP_PATH).canonicalize()?; if path_to_packages_zip_path != canonical_packages_zip_path { std::fs::copy(&path_to_packages_zip_path, &canonical_packages_zip_path)?; From 31365ecc79b69d6f15619ebbe850b66e89d03aeb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 00:19:34 +0000 Subject: [PATCH 40/43] Format Rust code using rustfmt --- kinode/build.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kinode/build.rs b/kinode/build.rs index b5d8b8be..046f0d55 100644 --- a/kinode/build.rs +++ b/kinode/build.rs @@ -35,13 +35,19 @@ fn main() -> anyhow::Result<()> { if !path.exists() { let path = std::env::current_dir()?; let Some(path) = path.parent() else { - return Err(anyhow::anyhow!("Given path to packages {env_var} not found (cwd: {:?})", std::env::current_dir())); + return Err(anyhow::anyhow!( + "Given path to packages {env_var} not found (cwd: {:?})", + std::env::current_dir() + )); }; let path = path.join(&env_var); if path.exists() { path.display().to_string() } else { - return Err(anyhow::anyhow!("Given path to packages {env_var} not found in parent of cwd: {:?}", std::env::current_dir())); + return Err(anyhow::anyhow!( + "Given path to packages {env_var} not found in parent of cwd: {:?}", + std::env::current_dir() + )); } } else { env_var From ae7e3228a4ff19547868e488f853fe9707f86e73 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 3 Dec 2024 17:01:46 -0800 Subject: [PATCH 41/43] remove `encrypted` & bump process_lib version --- Cargo.lock | 64 +++++++++---------- kinode/packages/app-store/Cargo.lock | 4 +- .../packages/app-store/app-store/Cargo.toml | 2 +- kinode/packages/app-store/chain/Cargo.toml | 2 +- kinode/packages/app-store/download/Cargo.toml | 2 +- .../packages/app-store/downloads/Cargo.toml | 2 +- .../packages/app-store/ft-worker/Cargo.toml | 2 +- kinode/packages/app-store/install/Cargo.toml | 2 +- .../packages/app-store/uninstall/Cargo.toml | 2 +- kinode/packages/chess/Cargo.lock | 4 +- kinode/packages/chess/chess/Cargo.toml | 2 +- kinode/packages/contacts/Cargo.lock | 4 +- kinode/packages/contacts/contacts/Cargo.toml | 2 +- kinode/packages/contacts/get-names/Cargo.toml | 2 +- kinode/packages/homepage/Cargo.lock | 4 +- kinode/packages/homepage/homepage/Cargo.toml | 2 +- kinode/packages/kino-updates/Cargo.lock | 4 +- kinode/packages/kino-updates/blog/Cargo.toml | 2 +- kinode/packages/kino-updates/globe/Cargo.toml | 2 +- kinode/packages/kns-indexer/Cargo.lock | 4 +- .../packages/kns-indexer/get-block/Cargo.toml | 2 +- .../kns-indexer/kns-indexer/Cargo.toml | 2 +- kinode/packages/kns-indexer/state/Cargo.toml | 2 +- kinode/packages/settings/Cargo.lock | 4 +- kinode/packages/settings/settings/Cargo.toml | 2 +- kinode/packages/terminal/Cargo.lock | 4 +- kinode/packages/terminal/alias/Cargo.toml | 2 +- kinode/packages/terminal/cat/Cargo.toml | 2 +- kinode/packages/terminal/echo/Cargo.toml | 2 +- kinode/packages/terminal/help/Cargo.toml | 2 +- kinode/packages/terminal/hi/Cargo.toml | 2 +- kinode/packages/terminal/kfetch/Cargo.toml | 2 +- kinode/packages/terminal/kill/Cargo.toml | 2 +- kinode/packages/terminal/m/Cargo.toml | 2 +- .../terminal/net-diagnostics/Cargo.toml | 2 +- kinode/packages/terminal/peer/Cargo.toml | 2 +- kinode/packages/terminal/peers/Cargo.toml | 2 +- kinode/packages/terminal/terminal/Cargo.toml | 2 +- kinode/packages/terminal/top/Cargo.toml | 2 +- kinode/packages/tester/Cargo.lock | 4 +- kinode/packages/tester/tester/Cargo.toml | 2 +- kinode/src/http/server.rs | 8 --- lib/src/http/server_types.rs | 7 +- 43 files changed, 82 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e0104c1..9c68f478 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,7 +84,7 @@ name = "alias" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -1036,7 +1036,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "rand 0.8.5", "serde", @@ -1419,7 +1419,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "url", @@ -1629,7 +1629,7 @@ name = "cat" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -1693,7 +1693,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "rand 0.8.5", "serde", @@ -1712,7 +1712,7 @@ version = "0.2.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "pleco", "serde", "serde_json", @@ -1904,7 +1904,7 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" name = "contacts" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "serde", "serde_json", @@ -2502,7 +2502,7 @@ name = "download" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "serde", "serde_json", @@ -2514,7 +2514,7 @@ name = "downloads" version = "0.5.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "rand 0.8.5", "serde", @@ -2551,7 +2551,7 @@ dependencies = [ name = "echo" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "wit-bindgen", ] @@ -2796,7 +2796,7 @@ version = "0.2.0" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "rand 0.8.5", "serde", @@ -2950,7 +2950,7 @@ dependencies = [ name = "get_block" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -3015,7 +3015,7 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" name = "globe" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "url", @@ -3152,7 +3152,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" name = "help" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "wit-bindgen", ] @@ -3181,7 +3181,7 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" name = "hi" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -3214,7 +3214,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -3657,7 +3657,7 @@ name = "install" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "serde", "serde_json", @@ -3834,7 +3834,7 @@ name = "kfetch" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rmp-serde", "serde", "serde_json", @@ -3846,7 +3846,7 @@ name = "kill" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -3942,8 +3942,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy 0.1.4", "alloy-primitives 0.7.7", @@ -4007,7 +4007,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "hex", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rmp-serde", "serde", "serde_json", @@ -4243,7 +4243,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "regex", "serde", "serde_json", @@ -4422,7 +4422,7 @@ dependencies = [ name = "net-diagnostics" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rmp-serde", "serde", "wit-bindgen", @@ -4759,7 +4759,7 @@ dependencies = [ name = "peer" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rmp-serde", "serde", "wit-bindgen", @@ -4769,7 +4769,7 @@ dependencies = [ name = "peers" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rmp-serde", "serde", "wit-bindgen", @@ -5809,7 +5809,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rmp-serde", "serde", "serde_json", @@ -6027,7 +6027,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "state" version = "0.1.0" dependencies = [ - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -6218,7 +6218,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "rand 0.8.5", "regex", "serde", @@ -6232,7 +6232,7 @@ version = "0.1.1" dependencies = [ "anyhow", "bincode", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "serde", "serde_json", @@ -6488,7 +6488,7 @@ version = "0.2.0" dependencies = [ "anyhow", "clap", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "serde", "serde_json", "wit-bindgen", @@ -6821,7 +6821,7 @@ name = "uninstall" version = "0.1.0" dependencies = [ "anyhow", - "kinode_process_lib 0.9.4", + "kinode_process_lib 0.10.0", "process_macros", "serde", "serde_json", diff --git a/kinode/packages/app-store/Cargo.lock b/kinode/packages/app-store/Cargo.lock index 66594791..0212ae50 100644 --- a/kinode/packages/app-store/Cargo.lock +++ b/kinode/packages/app-store/Cargo.lock @@ -1656,8 +1656,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/app-store/app-store/Cargo.toml b/kinode/packages/app-store/app-store/Cargo.toml index 11bb00f8..1a5c1743 100644 --- a/kinode/packages/app-store/app-store/Cargo.toml +++ b/kinode/packages/app-store/app-store/Cargo.toml @@ -11,7 +11,7 @@ alloy-primitives = "0.7.6" alloy-sol-types = "0.7.6" anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } rand = "0.8" serde = { version = "1.0", features = ["derive"] } diff --git a/kinode/packages/app-store/chain/Cargo.toml b/kinode/packages/app-store/chain/Cargo.toml index 05e8a57d..45c4a169 100644 --- a/kinode/packages/app-store/chain/Cargo.toml +++ b/kinode/packages/app-store/chain/Cargo.toml @@ -11,7 +11,7 @@ alloy-primitives = "0.7.6" alloy-sol-types = "0.7.6" anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } rand = "0.8" serde = { version = "1.0", features = ["derive"] } diff --git a/kinode/packages/app-store/download/Cargo.toml b/kinode/packages/app-store/download/Cargo.toml index ed64a9f0..364f4c86 100644 --- a/kinode/packages/app-store/download/Cargo.toml +++ b/kinode/packages/app-store/download/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/app-store/downloads/Cargo.toml b/kinode/packages/app-store/downloads/Cargo.toml index 21634fa3..fb7c58a9 100644 --- a/kinode/packages/app-store/downloads/Cargo.toml +++ b/kinode/packages/app-store/downloads/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } rand = "0.8" serde = { version = "1.0", features = ["derive"] } diff --git a/kinode/packages/app-store/ft-worker/Cargo.toml b/kinode/packages/app-store/ft-worker/Cargo.toml index 97021d65..de234cc2 100644 --- a/kinode/packages/app-store/ft-worker/Cargo.toml +++ b/kinode/packages/app-store/ft-worker/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } rand = "0.8" serde = { version = "1.0", features = ["derive"] } diff --git a/kinode/packages/app-store/install/Cargo.toml b/kinode/packages/app-store/install/Cargo.toml index 0b9b693a..f79fa55a 100644 --- a/kinode/packages/app-store/install/Cargo.toml +++ b/kinode/packages/app-store/install/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/app-store/uninstall/Cargo.toml b/kinode/packages/app-store/uninstall/Cargo.toml index 8e0b9c2f..fdac4d83 100644 --- a/kinode/packages/app-store/uninstall/Cargo.toml +++ b/kinode/packages/app-store/uninstall/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/chess/Cargo.lock b/kinode/packages/chess/Cargo.lock index e5e0a921..1f77ff06 100644 --- a/kinode/packages/chess/Cargo.lock +++ b/kinode/packages/chess/Cargo.lock @@ -1559,8 +1559,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/chess/chess/Cargo.toml b/kinode/packages/chess/chess/Cargo.toml index e6f2e77f..e6dce69f 100644 --- a/kinode/packages/chess/chess/Cargo.toml +++ b/kinode/packages/chess/chess/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } pleco = "0.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/contacts/Cargo.lock b/kinode/packages/contacts/Cargo.lock index ad0c0f7f..72efe937 100644 --- a/kinode/packages/contacts/Cargo.lock +++ b/kinode/packages/contacts/Cargo.lock @@ -1514,8 +1514,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/contacts/contacts/Cargo.toml b/kinode/packages/contacts/contacts/Cargo.toml index 49ed2b91..b1568a6d 100644 --- a/kinode/packages/contacts/contacts/Cargo.toml +++ b/kinode/packages/contacts/contacts/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/contacts/get-names/Cargo.toml b/kinode/packages/contacts/get-names/Cargo.toml index 94cbeae5..a797e3d8 100644 --- a/kinode/packages/contacts/get-names/Cargo.toml +++ b/kinode/packages/contacts/get-names/Cargo.toml @@ -6,7 +6,7 @@ publish = false [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/homepage/Cargo.lock b/kinode/packages/homepage/Cargo.lock index 87f6dc28..9ee6865f 100644 --- a/kinode/packages/homepage/Cargo.lock +++ b/kinode/packages/homepage/Cargo.lock @@ -1503,8 +1503,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/homepage/homepage/Cargo.toml b/kinode/packages/homepage/homepage/Cargo.toml index d26d6027..758f9d52 100644 --- a/kinode/packages/homepage/homepage/Cargo.toml +++ b/kinode/packages/homepage/homepage/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/kino-updates/Cargo.lock b/kinode/packages/kino-updates/Cargo.lock index 7d32af5a..784b3a8c 100644 --- a/kinode/packages/kino-updates/Cargo.lock +++ b/kinode/packages/kino-updates/Cargo.lock @@ -1515,8 +1515,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/kino-updates/blog/Cargo.toml b/kinode/packages/kino-updates/blog/Cargo.toml index 04bfd65b..afa6607f 100644 --- a/kinode/packages/kino-updates/blog/Cargo.toml +++ b/kinode/packages/kino-updates/blog/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" url = "2.5.0" diff --git a/kinode/packages/kino-updates/globe/Cargo.toml b/kinode/packages/kino-updates/globe/Cargo.toml index 4c7e1edb..81ace65a 100644 --- a/kinode/packages/kino-updates/globe/Cargo.toml +++ b/kinode/packages/kino-updates/globe/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" url = "2.5.0" diff --git a/kinode/packages/kns-indexer/Cargo.lock b/kinode/packages/kns-indexer/Cargo.lock index 17a230ac..2e35fb28 100644 --- a/kinode/packages/kns-indexer/Cargo.lock +++ b/kinode/packages/kns-indexer/Cargo.lock @@ -1501,8 +1501,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/kns-indexer/get-block/Cargo.toml b/kinode/packages/kns-indexer/get-block/Cargo.toml index a8f098d2..d2da1546 100644 --- a/kinode/packages/kns-indexer/get-block/Cargo.toml +++ b/kinode/packages/kns-indexer/get-block/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/kns-indexer/kns-indexer/Cargo.toml b/kinode/packages/kns-indexer/kns-indexer/Cargo.toml index 872391d6..a4c802de 100644 --- a/kinode/packages/kns-indexer/kns-indexer/Cargo.toml +++ b/kinode/packages/kns-indexer/kns-indexer/Cargo.toml @@ -11,7 +11,7 @@ anyhow = "1.0" alloy-primitives = "0.7.0" alloy-sol-types = "0.7.0" hex = "0.4.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rmp-serde = "1.1.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/kns-indexer/state/Cargo.toml b/kinode/packages/kns-indexer/state/Cargo.toml index 60570639..8b008062 100644 --- a/kinode/packages/kns-indexer/state/Cargo.toml +++ b/kinode/packages/kns-indexer/state/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/settings/Cargo.lock b/kinode/packages/settings/Cargo.lock index 39c17b69..180b0814 100644 --- a/kinode/packages/settings/Cargo.lock +++ b/kinode/packages/settings/Cargo.lock @@ -1491,8 +1491,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/settings/settings/Cargo.toml b/kinode/packages/settings/settings/Cargo.toml index f7e03d17..7e734a0e 100644 --- a/kinode/packages/settings/settings/Cargo.toml +++ b/kinode/packages/settings/settings/Cargo.toml @@ -10,7 +10,7 @@ simulation-mode = [] anyhow = "1.0" base64 = "0.22.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rmp-serde = "1.2.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/terminal/Cargo.lock b/kinode/packages/terminal/Cargo.lock index ae0db4f6..ca776dcc 100644 --- a/kinode/packages/terminal/Cargo.lock +++ b/kinode/packages/terminal/Cargo.lock @@ -1659,8 +1659,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/terminal/alias/Cargo.toml b/kinode/packages/terminal/alias/Cargo.toml index 5df83aef..cbfce7b4 100644 --- a/kinode/packages/terminal/alias/Cargo.toml +++ b/kinode/packages/terminal/alias/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/cat/Cargo.toml b/kinode/packages/terminal/cat/Cargo.toml index 2f07268a..3dfe073e 100644 --- a/kinode/packages/terminal/cat/Cargo.toml +++ b/kinode/packages/terminal/cat/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/echo/Cargo.toml b/kinode/packages/terminal/echo/Cargo.toml index ee9e7ee0..2ae9fae6 100644 --- a/kinode/packages/terminal/echo/Cargo.toml +++ b/kinode/packages/terminal/echo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } wit-bindgen = "0.24.0" [lib] diff --git a/kinode/packages/terminal/help/Cargo.toml b/kinode/packages/terminal/help/Cargo.toml index 4133661c..5267de44 100644 --- a/kinode/packages/terminal/help/Cargo.toml +++ b/kinode/packages/terminal/help/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } wit-bindgen = "0.24.0" [lib] diff --git a/kinode/packages/terminal/hi/Cargo.toml b/kinode/packages/terminal/hi/Cargo.toml index 1becd495..1fa90b13 100644 --- a/kinode/packages/terminal/hi/Cargo.toml +++ b/kinode/packages/terminal/hi/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/kfetch/Cargo.toml b/kinode/packages/terminal/kfetch/Cargo.toml index ff7c5c80..4ca2f290 100644 --- a/kinode/packages/terminal/kfetch/Cargo.toml +++ b/kinode/packages/terminal/kfetch/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rmp-serde = "1.1.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/terminal/kill/Cargo.toml b/kinode/packages/terminal/kill/Cargo.toml index afb56861..086f4298 100644 --- a/kinode/packages/terminal/kill/Cargo.toml +++ b/kinode/packages/terminal/kill/Cargo.toml @@ -8,7 +8,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/m/Cargo.toml b/kinode/packages/terminal/m/Cargo.toml index f5ab2892..dd57036c 100644 --- a/kinode/packages/terminal/m/Cargo.toml +++ b/kinode/packages/terminal/m/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" clap = "4.4" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } regex = "1.10.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/packages/terminal/net-diagnostics/Cargo.toml b/kinode/packages/terminal/net-diagnostics/Cargo.toml index ab49e122..bb4d866f 100644 --- a/kinode/packages/terminal/net-diagnostics/Cargo.toml +++ b/kinode/packages/terminal/net-diagnostics/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rmp-serde = "1.1.2" serde = { version = "1.0", features = ["derive"] } wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/peer/Cargo.toml b/kinode/packages/terminal/peer/Cargo.toml index c07a5a96..c3eb44e4 100644 --- a/kinode/packages/terminal/peer/Cargo.toml +++ b/kinode/packages/terminal/peer/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rmp-serde = "1.1.2" serde = { version = "1.0", features = ["derive"] } wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/peers/Cargo.toml b/kinode/packages/terminal/peers/Cargo.toml index 0ea578e4..02694dce 100644 --- a/kinode/packages/terminal/peers/Cargo.toml +++ b/kinode/packages/terminal/peers/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" simulation-mode = [] [dependencies] -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rmp-serde = "1.1.2" serde = { version = "1.0", features = ["derive"] } wit-bindgen = "0.24.0" diff --git a/kinode/packages/terminal/terminal/Cargo.toml b/kinode/packages/terminal/terminal/Cargo.toml index eabe43b7..cef553b5 100644 --- a/kinode/packages/terminal/terminal/Cargo.toml +++ b/kinode/packages/terminal/terminal/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } rand = "0.8" regex = "1.10.3" serde = { version = "1.0", features = ["derive"] } diff --git a/kinode/packages/terminal/top/Cargo.toml b/kinode/packages/terminal/top/Cargo.toml index 7afb9895..949b24da 100644 --- a/kinode/packages/terminal/top/Cargo.toml +++ b/kinode/packages/terminal/top/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" clap = "4.4" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" wit-bindgen = "0.24.0" diff --git a/kinode/packages/tester/Cargo.lock b/kinode/packages/tester/Cargo.lock index 79a54429..213e1ce4 100644 --- a/kinode/packages/tester/Cargo.lock +++ b/kinode/packages/tester/Cargo.lock @@ -1491,8 +1491,8 @@ dependencies = [ [[package]] name = "kinode_process_lib" -version = "0.9.4" -source = "git+https://github.com/kinode-dao/process_lib?rev=778457a#778457ae52c934fd17e0e846127a9472a8e03170" +version = "0.10.0" +source = "git+https://github.com/kinode-dao/process_lib?rev=1fe8612#1fe8612a24f6806270ac9b02c7bd4f464a1422ed" dependencies = [ "alloy", "alloy-primitives 0.7.7", diff --git a/kinode/packages/tester/tester/Cargo.toml b/kinode/packages/tester/tester/Cargo.toml index 7ea6a351..ac55e33e 100644 --- a/kinode/packages/tester/tester/Cargo.toml +++ b/kinode/packages/tester/tester/Cargo.toml @@ -9,7 +9,7 @@ simulation-mode = [] [dependencies] anyhow = "1.0" bincode = "1.3.3" -kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "778457a" } +kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "1fe8612" } process_macros = { git = "https://github.com/kinode-dao/process_macros", rev = "626e501" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index cb69db55..c55a2d47 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -63,7 +63,6 @@ struct BoundWsPath { pub app: Option, // if None, path has been unbound pub secure_subdomain: Option, pub authenticated: bool, - pub encrypted: bool, // TODO use pub extension: bool, } @@ -531,7 +530,6 @@ async fn ws_handler( our.clone(), app, formatted_path, - jwt_secret_bytes.clone(), ws_senders.clone(), send_to_loop.clone(), print_tx.clone(), @@ -975,7 +973,6 @@ async fn maintain_websocket( our: Arc, app: ProcessId, path: String, - _jwt_secret_bytes: Arc>, // TODO use for encrypted channels ws_senders: WebSocketSenders, send_to_loop: MessageSender, print_tx: PrintSender, @@ -1330,7 +1327,6 @@ async fn handle_app_message( HttpServerAction::WebSocketBind { path, authenticated, - encrypted, extension, } => { if check_process_id_kimap_safe(&km.source.process).is_err() { @@ -1357,14 +1353,12 @@ async fn handle_app_message( app: Some(km.source.process.clone()), secure_subdomain: None, authenticated, - encrypted, extension, }, ); } HttpServerAction::WebSocketSecureBind { path, - encrypted, extension, } => { if check_process_id_kimap_safe(&km.source.process).is_err() { @@ -1392,7 +1386,6 @@ async fn handle_app_message( app: Some(km.source.process.clone()), secure_subdomain: Some(subdomain), authenticated: true, - encrypted, extension, }, ); @@ -1406,7 +1399,6 @@ async fn handle_app_message( app: None, secure_subdomain: None, authenticated: false, - encrypted: false, extension: false, }, ); diff --git a/lib/src/http/server_types.rs b/lib/src/http/server_types.rs index 9b1ec87b..e0d9682e 100644 --- a/lib/src/http/server_types.rs +++ b/lib/src/http/server_types.rs @@ -102,18 +102,13 @@ pub enum HttpServerAction { WebSocketBind { path: String, authenticated: bool, - encrypted: bool, extension: bool, }, /// SecureBind is the same as Bind, except that it forces new connections to be made /// from the unique subdomain of the process that bound the path. These are *always* /// authenticated. Since the subdomain is unique, it will require the user to be /// logged in separately to the general domain authentication. - WebSocketSecureBind { - path: String, - encrypted: bool, - extension: bool, - }, + WebSocketSecureBind { path: String, extension: bool }, /// Unbind a previously-bound WebSocket path WebSocketUnbind { path: String }, /// Processes will RECEIVE this kind of request when a client connects to them. From b8a41534294853024fdbbcb12b0c1f15ecd5810b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 01:02:12 +0000 Subject: [PATCH 42/43] Format Rust code using rustfmt --- kinode/src/http/server.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index c55a2d47..7efe390f 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -1357,10 +1357,7 @@ async fn handle_app_message( }, ); } - HttpServerAction::WebSocketSecureBind { - path, - extension, - } => { + HttpServerAction::WebSocketSecureBind { path, extension } => { if check_process_id_kimap_safe(&km.source.process).is_err() { let source = km.source.clone(); send_action_response( From f602811a0347ee31cd7a5559ccf9222ef398b395 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Wed, 4 Dec 2024 12:20:32 -0500 Subject: [PATCH 43/43] fix: allow `:`, `.` in SSDs in auth cookie --- kinode/src/http/server.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kinode/src/http/server.rs b/kinode/src/http/server.rs index cb69db55..80146dc4 100644 --- a/kinode/src/http/server.rs +++ b/kinode/src/http/server.rs @@ -376,10 +376,12 @@ async fn login_handler( let cookie = match info.subdomain.unwrap_or_default().as_str() { "" => format!("kinode-auth_{our}={token};"), subdomain => { - // enforce that subdomain string only contains a-z, 0-9, and - + // enforce that subdomain string only contains a-z, 0-9, ., :, and - let subdomain = subdomain .chars() - .filter(|c| c.is_ascii_alphanumeric() || c == &'-') + .filter(|c| { + c.is_ascii_alphanumeric() || c == &'-' || c == &':' || c == &'.' + }) .collect::(); format!("kinode-auth_{our}@{subdomain}={token};") }