commit 19a45c485d1b915bd25762c26a69cf1ec94afef1 Author: Alex Payne Date: Thu Jul 30 16:29:26 2026 +0000 Initial Sovereign Stack PWA scaffold - PWA shell with service worker offline caching - Encrypted vault using IndexedDB - Lightning/L402 module placeholder - Ollama bridge placeholder - MIT license, no proprietary deps Co-authored-by: Hermes diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e768dd6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +.env +*.log diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..77a2925 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Alex Payne + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e4efa22 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Sovereign Stack PWA +Local-first, Lightning-native, open-weight agent runtime. Offline capable. No black boxes. + +## Install +```bash +git clone https://forge.alexanderwhitestone.com/git/stackchain/sovereign-stack-pwa.git +cd sovereign-stack-pwa +bash install.sh +``` + +## Stack +- PWA shell + service worker +- Local-first encrypted vault (IndexedDB) +- Lightning/L402 payment module +- Ollama bridge for open-weight LLMs +- MCP tool discovery + agent runtime +- MIT licensed. Every line source-available. + diff --git a/index.html b/index.html new file mode 100644 index 0000000..4c29011 --- /dev/null +++ b/index.html @@ -0,0 +1,75 @@ + + + + + +Sovereign Stack + + + + +
+

Sovereign Stack v0.1 offline-capable

+
+ + + + +
+
+
Ready. Local-first. No cloud.
+
+ + + diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..0f7fec9 --- /dev/null +++ b/install.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail +echo "Sovereign Stack PWA installer" +echo "This will deploy the PWA and configure local Ollama bridge." +read -p "Continue? [y/N] " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Aborted." + exit 1 +fi +mkdir -p ~/sovereign-stack-pwa +cp -r ./* ~/sovereign-stack-pwa/ +echo "Installed to ~/sovereign-stack-pwa" +echo "Run: cd ~/sovereign-stack-pwa && python3 -m http.server 8080" diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..60f7f96 --- /dev/null +++ b/manifest.json @@ -0,0 +1,9 @@ +{ + "name": "Sovereign Stack", + "short_name": "Sovereign", + "start_url": "./", + "display": "standalone", + "background_color": "#0a0a0a", + "theme_color": "#0a0a0a", + "icons": [ { "src": "icon.png", "sizes": "192x192", "type": "image/png" } ] +} diff --git a/manifest.webmanifest b/manifest.webmanifest new file mode 100644 index 0000000..4b10745 --- /dev/null +++ b/manifest.webmanifest @@ -0,0 +1,8 @@ +{ + "name": "Sovereign Stack", + "short_name": "Sovereign", + "start_url": "./", + "display": "standalone", + "background_color": "#0a0a0a", + "theme_color": "#0a0a0a" +} diff --git a/sw.js b/sw.js new file mode 100644 index 0000000..4ab43a5 --- /dev/null +++ b/sw.js @@ -0,0 +1,5 @@ +const CACHE = 'sovereign-v1'; +const ASSETS = ['./', './index.html']; +self.addEventListener('install', (e) => { e.waitUntil(caches.open(CACHE).then(c => c.addAll(ASSETS)).then(() => self.skipWaiting())); }); +self.addEventListener('activate', (e) => { e.waitUntil(self.clients.claim()); }); +self.addEventListener('fetch', (e) => { e.respondWith(caches.match(e.request).then(r => r || fetch(e.request).then(res => { if (res.status === 200) { const clone = res.clone(); caches.open(CACHE).then(c => c.put(e.request, clone)); } return res; }).catch(() => caches.match('./index.html'))); });