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 <hermes@nousresearch.com>
This commit is contained in:
commit
19a45c485d
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
.env
|
||||
*.log
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -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.
|
||||
18
README.md
Normal file
18
README.md
Normal file
|
|
@ -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.
|
||||
|
||||
75
index.html
Normal file
75
index.html
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sovereign Stack</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<style>
|
||||
body { font-family: system-ui, sans-serif; background: #0a0a0a; color: #e0e0e0; margin: 0; padding: 1rem; }
|
||||
.container { max-width: 720px; margin: 0 auto; }
|
||||
h1 { font-size: 1.25rem; margin: 0 0 0.5rem; }
|
||||
.status { font-size: 0.75rem; color: #888; }
|
||||
.vault { background: #111; border: 1px solid #222; padding: 1rem; margin: 1rem 0; border-radius: 0.5rem; }
|
||||
input, textarea { width: 100%; background: #0a0a0a; color: #e0e0e0; border: 1px solid #333; padding: 0.5rem; margin: 0.25rem 0; border-radius: 0.25rem; }
|
||||
button { background: #222; color: #e0e0e0; border: 1px solid #444; padding: 0.5rem 1rem; border-radius: 0.25rem; cursor: pointer; }
|
||||
button:hover { background: #333; }
|
||||
.log { font-family: monospace; font-size: 0.7rem; color: #888; margin-top: 1rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Sovereign Stack <span class="status">v0.1 offline-capable</span></h1>
|
||||
<div class="vault">
|
||||
<input id="entryTitle" placeholder="Title" />
|
||||
<textarea id="entryBody" rows="4" placeholder="Encrypted note..."></textarea>
|
||||
<button onclick="saveEntry()">Save to Vault</button>
|
||||
<button onclick="loadEntries()">Refresh</button>
|
||||
</div>
|
||||
<div id="entries"></div>
|
||||
<div class="log" id="log">Ready. Local-first. No cloud.</div>
|
||||
</div>
|
||||
<script>
|
||||
const dbName = 'sovereign-vault';
|
||||
const storeName = 'entries';
|
||||
let db;
|
||||
|
||||
function log(msg) { document.getElementById('log').textContent = msg; }
|
||||
|
||||
function openDB() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = indexedDB.open(dbName, 1);
|
||||
req.onupgradeneeded = (e) => {
|
||||
const d = e.target.result;
|
||||
if (!d.objectStoreNames.contains(storeName)) d.createObjectStore(storeName, { keyPath: 'id', autoIncrement: true });
|
||||
};
|
||||
req.onsuccess = (e) => { db = e.target.result; resolve(db); };
|
||||
req.onerror = (e) => reject(e.target.error);
|
||||
});
|
||||
}
|
||||
|
||||
async function saveEntry() {
|
||||
await openDB();
|
||||
const title = document.getElementById('entryTitle').value.trim();
|
||||
const body = document.getElementById('entryBody').value.trim();
|
||||
if (!title && !body) return log('Nothing to save.');
|
||||
const tx = db.transaction(storeName, 'readwrite');
|
||||
tx.objectStore(storeName).add({ title, body, ts: Date.now() });
|
||||
tx.oncomplete = () => { document.getElementById('entryTitle').value = ''; document.getElementById('entryBody').value = ''; log('Saved locally.'); loadEntries(); };
|
||||
}
|
||||
|
||||
async function loadEntries() {
|
||||
await openDB();
|
||||
const tx = db.transaction(storeName, 'readonly');
|
||||
const req = tx.objectStore(storeName).getAll();
|
||||
req.onsuccess = () => {
|
||||
const out = req.result.slice().reverse().slice(0, 20).map(e => `<div><strong>${e.title || 'Untitled'}</strong><div>${e.body || ''}</div><div style="color:#555">${new Date(e.ts).toISOString()}</div></div>`).join('');
|
||||
document.getElementById('entries').innerHTML = out || '<div style="color:#555">No entries yet.</div>';
|
||||
};
|
||||
}
|
||||
|
||||
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js').catch(() => log('SW registration failed')); }
|
||||
loadEntries();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
14
install.sh
Executable file
14
install.sh
Executable file
|
|
@ -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"
|
||||
9
manifest.json
Normal file
9
manifest.json
Normal file
|
|
@ -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" } ]
|
||||
}
|
||||
8
manifest.webmanifest
Normal file
8
manifest.webmanifest
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Sovereign Stack",
|
||||
"short_name": "Sovereign",
|
||||
"start_url": "./",
|
||||
"display": "standalone",
|
||||
"background_color": "#0a0a0a",
|
||||
"theme_color": "#0a0a0a"
|
||||
}
|
||||
5
sw.js
Normal file
5
sw.js
Normal file
|
|
@ -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'))); });
|
||||
Loading…
Reference in New Issue
Block a user