mirror of
https://github.com/PR0M3TH3AN/VoxVera.git
synced 2026-10-27 17:50:42 +00:00
Compare commits
No files matched your search
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "VoxVera",
|
||||
"build": {
|
||||
"dockerfile": "../Dockerfile",
|
||||
"context": ".."
|
||||
},
|
||||
"workspaceFolder": "/workspace/VoxVera"
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
name: Build Standalone Binaries
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build for ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, windows-latest, macos-latest]
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
artifact_name: voxvera-linux-x86_64
|
||||
- os: windows-latest
|
||||
artifact_name: voxvera-windows.exe
|
||||
- os: macos-latest
|
||||
artifact_name: voxvera-macos-x86_64
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install --upgrade setuptools pkg_resources || pip install --upgrade setuptools
|
||||
pip install -r requirements.txt
|
||||
pip install .
|
||||
pip install pyinstaller pyinstaller-hooks-contrib
|
||||
|
||||
- name: Download Tor Binaries
|
||||
shell: bash
|
||||
run: |
|
||||
chmod +x scripts/download_tor.sh
|
||||
./scripts/download_tor.sh
|
||||
|
||||
- name: Build with PyInstaller
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "$RUNNER_OS" == "Windows" ]; then SEP=";"; else SEP=":"; fi
|
||||
pyinstaller --onefile \
|
||||
--collect-all pkg_resources \
|
||||
--collect-all setuptools \
|
||||
--hidden-import pkg_resources \
|
||||
--hidden-import setuptools \
|
||||
--hidden-import jaraco.text \
|
||||
--hidden-import jaraco.functools \
|
||||
--hidden-import jaraco.context \
|
||||
--hidden-import more_itertools \
|
||||
--hidden-import packaging \
|
||||
--hidden-import platformdirs \
|
||||
--collect-all onionshare_cli \
|
||||
--collect-all flask_socketio \
|
||||
--collect-all engineio \
|
||||
--collect-all socketio \
|
||||
--collect-all eventlet \
|
||||
--collect-all gevent \
|
||||
--add-data "voxvera/locales${SEP}voxvera/locales" \
|
||||
--add-data "voxvera/src${SEP}voxvera/src" \
|
||||
--add-data "voxvera/templates${SEP}voxvera/templates" \
|
||||
--add-data "voxvera/resources/tor${SEP}voxvera/resources/tor" \
|
||||
--add-data "support-matrix.json${SEP}." \
|
||||
--add-data "requirements.txt${SEP}." \
|
||||
--name "${{ matrix.artifact_name }}" \
|
||||
voxvera/cli.py
|
||||
|
||||
- name: Validate built binary contract surface (Linux/macOS)
|
||||
if: matrix.os != 'windows-latest'
|
||||
shell: bash
|
||||
run: |
|
||||
./dist/${{ matrix.artifact_name }} platform-status --json
|
||||
./dist/${{ matrix.artifact_name }} doctor --json
|
||||
./dist/${{ matrix.artifact_name }} autostart status --json
|
||||
|
||||
- name: Validate built binary contract surface (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
shell: pwsh
|
||||
run: |
|
||||
& ".\dist\${{ matrix.artifact_name }}" platform-status --json
|
||||
& ".\dist\${{ matrix.artifact_name }}" doctor --json
|
||||
& ".\dist\${{ matrix.artifact_name }}" autostart status --json
|
||||
|
||||
- name: Build .deb (Linux)
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
mkdir -p voxvera/resources/bin
|
||||
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-linux-x86_64
|
||||
chmod +x packaging/build_deb.sh
|
||||
./packaging/build_deb.sh dist/${{ matrix.artifact_name }}
|
||||
|
||||
- name: Build AppImage (Linux)
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
mkdir -p voxvera/resources/bin
|
||||
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-linux-x86_64
|
||||
chmod +x packaging/build_appimage.sh
|
||||
./packaging/build_appimage.sh dist/${{ matrix.artifact_name }}
|
||||
|
||||
- name: Build Flatpak (Linux)
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
mkdir -p voxvera/resources/bin
|
||||
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-linux-x86_64
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y flatpak flatpak-builder
|
||||
chmod +x packaging/build_flatpak.sh
|
||||
./packaging/build_flatpak.sh dist/${{ matrix.artifact_name }} || echo "Flatpak build failed"
|
||||
|
||||
- name: Build .dmg (macOS)
|
||||
if: matrix.os == 'macos-latest'
|
||||
run: |
|
||||
mkdir -p voxvera/resources/bin
|
||||
cp dist/${{ matrix.artifact_name }} voxvera/resources/bin/voxvera-macos-x86_64
|
||||
chmod +x packaging/build_dmg.sh
|
||||
./packaging/build_dmg.sh dist/${{ matrix.artifact_name }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: binaries-${{ matrix.os }}
|
||||
path: |
|
||||
dist/${{ matrix.artifact_name }}
|
||||
voxvera/resources/bin/*.deb
|
||||
voxvera/resources/bin/*.dmg
|
||||
voxvera/resources/bin/*.AppImage
|
||||
voxvera/resources/bin/*.flatpak
|
||||
|
||||
publish:
|
||||
name: Create GitHub Release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Flatten artifacts for release
|
||||
run: |
|
||||
mkdir -p release_assets
|
||||
find artifacts -type f -exec cp {} release_assets/ \;
|
||||
ls -R release_assets/
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
release_assets/*
|
||||
fail_on_unmatched_files: false
|
||||
overwrite: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
+12
-49
@@ -2,63 +2,26 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
lint-test:
|
||||
static-client:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y tor
|
||||
python -m pip install --upgrade pip
|
||||
pip install flake8
|
||||
pip install -e ".[test]"
|
||||
pip install git+https://github.com/onionshare/onionshare.git#subdirectory=cli
|
||||
- name: Lint
|
||||
run: flake8 voxvera tests --exclude=voxvera/vendor --ignore=E501,W503,W293,E402,E306,E704,E261,F841,E302,F401,E401,F541
|
||||
- name: Test
|
||||
run: pytest tests/ -v
|
||||
- name: Platform smoke
|
||||
run: bash scripts/platform-smoke.sh linux-cli
|
||||
|
||||
platform-contract:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-latest
|
||||
smoke_target: macos-cli
|
||||
- os: windows-latest
|
||||
smoke_target: windows-cli
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
python-version: "3.12"
|
||||
- name: Install Python test dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[test]"
|
||||
- name: Verify smoke target listing
|
||||
shell: bash
|
||||
run: bash scripts/platform-smoke.sh list
|
||||
- name: Validate platform-status JSON
|
||||
shell: bash
|
||||
run: python -m voxvera.cli platform-status --json
|
||||
- name: Validate doctor JSON
|
||||
shell: bash
|
||||
run: python -m voxvera.cli doctor --json
|
||||
- name: Validate autostart JSON
|
||||
shell: bash
|
||||
run: python -m voxvera.cli autostart status --json
|
||||
- name: Check frontend JavaScript
|
||||
run: node --check site/nostr/nostr-client.js
|
||||
- name: Run tests
|
||||
run: pytest -q
|
||||
@@ -1,31 +0,0 @@
|
||||
name: E2E
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y tor
|
||||
python -m pip install --upgrade pip
|
||||
pip install -e ".[e2e]"
|
||||
- name: Run end-to-end tests
|
||||
run: ci/test-e2e.sh
|
||||
continue-on-error: true
|
||||
- name: Upload logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ci-logs
|
||||
path: ci-logs/
|
||||
+23
-51
@@ -1,59 +1,31 @@
|
||||
# Temporary files
|
||||
*.tmp
|
||||
tmp*/
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.pytest_cache/
|
||||
*.egg-info/
|
||||
.venv/
|
||||
venv/
|
||||
.venv
|
||||
!voxvera/
|
||||
!voxvera/resources/**
|
||||
!voxvera/src/**
|
||||
|
||||
# OS and editor files
|
||||
# Node/browser tooling
|
||||
node_modules/
|
||||
|
||||
# Playwright e2e output
|
||||
test-results/
|
||||
playwright-report/
|
||||
playwright/.cache/
|
||||
|
||||
# Build and local output
|
||||
build/
|
||||
dist/
|
||||
ci-logs/
|
||||
|
||||
# OS/editor noise
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*~
|
||||
*.swp
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Build and distribution artifacts
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
|
||||
# Electron app artifacts
|
||||
gui/electron/node_modules/
|
||||
gui/electron/dist/
|
||||
gui/electron/build/
|
||||
gui/electron/out/
|
||||
|
||||
# Generated host directories
|
||||
host/*
|
||||
!host/voxvera/
|
||||
|
||||
# CI logs
|
||||
ci-logs/
|
||||
|
||||
# Onionshare logs and session files
|
||||
# Local browser/debug artifacts
|
||||
*.log
|
||||
*.onionshare-session
|
||||
gui/electron/package-lock.json
|
||||
voxvera/src/config.json
|
||||
voxvera/src/index.html
|
||||
voxvera/src/nostr.html
|
||||
voxvera/src/qrcode-content.png
|
||||
voxvera/src/qrcode-tear-offs.png
|
||||
|
||||
# PyInstaller
|
||||
*.spec
|
||||
dist_bin/
|
||||
voxvera/resources/bin/*
|
||||
!voxvera/resources/bin/.gitkeep
|
||||
site/download/*.zip
|
||||
!site/download/voxvera-source.zip
|
||||
site/download/*.exe
|
||||
site/download/*.deb
|
||||
site/download/*.dmg
|
||||
site/download/*.AppImage
|
||||
site/download/*.flatpak
|
||||
site/download/voxvera-linux
|
||||
site/download/voxvera-linux-x86_64
|
||||
*.pdf
|
||||
.vercel
|
||||
@@ -1,42 +1,50 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
# AI Agent Instructions For VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
`main` is the Nostr static-client branch. The old Tor/OnionShare CLI application is preserved on `legacy-tor`.
|
||||
|
||||
## Core Mandates
|
||||
## Current Architecture
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
- Active frontend: `site/` (`index.html`, `nostr-client.js`, `nostr-client.css`, `locales.js`)
|
||||
- Bulletin board: `site/board.html` + `site/board.js` (standalone page listing recent flyers from the relays; escapes untrusted relay content and rejects non-http(s) link URLs)
|
||||
- Static deployment root: `site`
|
||||
- Browser dependencies: vendored under `site/vendor/`
|
||||
- Legacy path: `site/nostr/index.html` is a redirect stub forwarding old `/nostr/` poster URLs and QR codes to the root
|
||||
- Python helper package: `voxvera/nostr/`
|
||||
- Design plan: `docs/nostr-static-client-spec.md`
|
||||
|
||||
## Localization Protocol
|
||||
## Guardrails
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
- Do not reintroduce the legacy Tor CLI, OnionShare runtime, installer, Electron manager, bundled Tor binaries, generated old flyer site, or packaging workflows on `main`.
|
||||
- Keep the Nostr client static and host-agnostic.
|
||||
- Do not load frontend dependencies from CDNs.
|
||||
- Treat Nostr event content as untrusted. Escape rendered content and reject unsafe schema input.
|
||||
- Preserve print behavior: app controls must not print or shift the flyer sheet in print output.
|
||||
- Preserve the old flyer visual language unless the user explicitly asks for a redesign.
|
||||
- Paper size (US Letter / A4) is a local print/view preference (`localStorage`), defaulted from the browser locale region. Never write it into the Nostr event — a flyer must reprint on either size without changing the source event.
|
||||
|
||||
## Universal Mirroring
|
||||
## Localization
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
- Use `site/locales.js` for flyer content defaults.
|
||||
- Use `NOSTR_UI` in `site/nostr-client.js` for editor/viewer controls and Nostr-specific labels.
|
||||
- Add translations for every supported language when adding user-facing strings.
|
||||
- Check right-to-left languages when touching layout.
|
||||
|
||||
## Verification Checklist
|
||||
## Verification
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
Run:
|
||||
|
||||
---
|
||||
```bash
|
||||
node --check site/nostr-client.js
|
||||
pytest -q
|
||||
```
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
For visual or print changes, also run a local static server and inspect the site root (`/`) in a browser.
|
||||
|
||||
Cross-browser end-to-end tests live in `e2e/` (Playwright; Chromium, Firefox, WebKit, plus mobile emulations). Run them after changes that touch rendering, print, key generation, URL/redirect handling, or the loading state:
|
||||
|
||||
```bash
|
||||
npm install && npx playwright install
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
WebKit/Safari on Linux needs `sudo npx playwright install-deps` once. See `e2e/README.md`. Test tooling is a dev dependency only — it must not pull runtime frontend dependencies from CDNs or otherwise weaken the static, host-agnostic client.
|
||||
+30
-38
@@ -1,48 +1,40 @@
|
||||
# Contributing to VoxVera
|
||||
# Contributing To VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
VoxVera `main` is a static Nostr client. Keep contributions focused on the browser editor/viewer, Nostr event validation, printable flyer rendering, and static deployment.
|
||||
|
||||
## Adding a New Language
|
||||
## Frontend
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
- Edit the active app under `site/nostr/`.
|
||||
- Keep dependencies vendored under `site/nostr/vendor/`; do not rely on CDNs.
|
||||
- Preserve viewer mode as a flyer-first experience.
|
||||
- Keep editor, load, print, language, and other controls hidden from print output.
|
||||
- Verify print layout after changes that affect the flyer surface.
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
## Localization
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
The static client currently uses `site/nostr/locales.js` plus the `NOSTR_UI` table in `site/nostr/nostr-client.js`.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
When adding user-facing text:
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
- Add translations for every supported language.
|
||||
- Check right-to-left languages in the browser where layout may be affected.
|
||||
- Keep side-tab strings short enough for tear-off strips.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Recommended local check**: Run `bash scripts/check.sh` before opening a PR. It mirrors the main lint/test/build checks in one command.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
## Nostr Schema
|
||||
|
||||
---
|
||||
Python validation helpers live in `voxvera/nostr/`. Keep the schema conservative:
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
- Reject raw HTML in user-supplied flyer fields.
|
||||
- Reject unsupported URL schemes.
|
||||
- Keep attachments out of V1 events unless the spec is deliberately expanded.
|
||||
|
||||
## Verification
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
node --check site/nostr/nostr-client.js
|
||||
pytest -q
|
||||
```
|
||||
|
||||
For UI work, also run a local static server and inspect `/nostr/` in a browser.
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Experimental container path: Linux systemd remains the supported
|
||||
# persistent-host deployment target.
|
||||
|
||||
# Install system dependencies (only runtime)
|
||||
RUN apt-get update && apt-get install -y \
|
||||
tor onionshare-cli \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy VoxVera source
|
||||
COPY . /opt/voxvera
|
||||
WORKDIR /opt/voxvera
|
||||
|
||||
# Install VoxVera and its Python dependencies
|
||||
RUN pip install .
|
||||
|
||||
# Prepare flyers volume
|
||||
RUN mkdir /flyers
|
||||
ENV VOXVERA_DIR=/flyers
|
||||
VOLUME /flyers
|
||||
|
||||
# Seed a default config when the volume is empty, then retry startup periodically.
|
||||
CMD ["sh", "-lc", "mkdir -p /flyers && if [ ! -f /flyers/config.json ]; then cp /opt/voxvera/voxvera/src/config.json /flyers/config.json; fi && voxvera quickstart --non-interactive && while true; do sleep 300; voxvera start-all || true; done"]
|
||||
@@ -1,5 +0,0 @@
|
||||
include voxvera/templates/**
|
||||
include voxvera/src/**
|
||||
include voxvera/resources/**
|
||||
include voxvera/locales/**
|
||||
include voxvera/resources/bin/**
|
||||
@@ -1,92 +1,90 @@
|
||||
# VoxVera
|
||||
|
||||
**Anonymous Information Distribution Engine**
|
||||
VoxVera is a static, Nostr-powered flyer client.
|
||||
|
||||
Generate printable flyers with QR codes linking to Tor (.onion) hidden services. VoxVera is built for activists, journalists, and anyone who needs to spread a message securely and anonymously.
|
||||
The active app lives at the site root ([`site/`](site/)). It lets anyone author flyer content, publish it as a public Nostr event, and re-render or reprint the flyer later from a Nostr address or event ID — no application server. The frontend is intentionally self-contained: Nostr relays store the content, and any static host can serve the client.
|
||||
|
||||
---
|
||||
The previous Tor/OnionShare CLI version is preserved on the `legacy-tor` branch.
|
||||
|
||||
## Installation
|
||||
## Features
|
||||
|
||||
VoxVera is designed for maximum portability and censorship resistance.
|
||||
- **Author and publish.** Fill in the flyer fields and publish them as a Nostr `30078` parameterized replaceable event. Republishing with the same flyer name replaces the previous version.
|
||||
- **Anonymous by default, your identity if you want it.** The editor signs flyers under one of four identities: an **anonymous** per-device key (default, no setup), a **NIP-07 browser extension** (your secret never touches the page), an **imported `nsec`**, or a **NIP-46 remote signer** (paste a `bunker://` link or scan a `nostrconnect://` QR with your signer app — your secret stays in the app, the browser holds only an ephemeral key; session-only). An imported key signs in-memory for the session; tick "Remember on this device" to keep it, encrypted with a PIN (PBKDF2 → AES-GCM) — the plaintext secret is never stored. A short PIN is a convenience lock, not protection against a targeted attacker (see the [spec](docs/nostr-static-client-spec.md#publishing-identity)); the extension and remote-signer paths are stronger.
|
||||
- **Publish confirmation.** After signing and publishing, a modal shows the new flyer's URL to copy, so authors know they're done and where to find it (localized, like everything else).
|
||||
- **Edit, re-publish, and delete your flyers.** Because flyers are replaceable events, the author can edit one in place (same key + Flyer Name keeps the same URL), re-publish it as a keep-alive so relays don't age it out, or delete it. Delete publishes a replaceable **tombstone** (so VoxVera hides it even where relays ignore deletions) **and** a NIP-09 deletion request — best-effort, author-only.
|
||||
- **Import / export a flyer design.** Save the current flyer as a portable `.json` file and load it back later — or hand it to someone else. The design file holds the content and relay list but **nothing identity-bound** (no npub, address, or signature; those are generated at publish), so a recipient can import it and publish under their own key. Importing asks for confirmation before replacing what's in the editor.
|
||||
- **Open from a link or ID.** Load a flyer from an `naddr`, `nevent1`, `note1`, raw 64-char event ID, or `nostr:` URL. The lookup field tolerates copy/paste whitespace and newlines, so an event ID copied off a printed tear-off (where it wraps across two lines) still resolves.
|
||||
- **Short, scannable poster URLs.** Each poster URL is a standard NIP-19 `naddr` carrying a single relay hint, placed in the URL `#fragment` (no `?addr=` query). Shorter URLs make the tear-off QR code easier to scan. Older relay-list `naddr`s and `?addr=` URLs still resolve.
|
||||
- **Tear-off tabs.** The printable flyer has ten tear-off tabs. Each tab is labeled with the flyer's **title** (auto-sized to be as large as fits), a clickable **"Open & reprint this flyer"** link (live in the printed PDF), a QR code, and a **"Reopen at VoxVera.org — Event ID:"** line with the full event ID so anyone can re-find and reprint the flyer by typing it in. Localized in every language.
|
||||
- **Loading state on shared links.** Opening a poster/event link shows a localized "Loading content…" placeholder (and a "Could not load this flyer." state on failure) instead of the default flyer; the default sample content appears only on the bare site URL.
|
||||
- **14 languages with RTL support.** Flyer content and UI are localized; right-to-left scripts render correctly. Letter-spacing is applied per script so cursive (Arabic/Persian) and combining (Devanagari) scripts are not broken — see [the spec](docs/nostr-static-client-spec.md#letter-spacing-by-script).
|
||||
- **US Letter and A4.** Print size defaults to the right paper for the visitor's country (from the browser locale's region — `en-US` → Letter, `en-GB` → A4, no geolocation), with a manual override. Paper size is a local print preference and is never written into the event. See the [spec](docs/nostr-static-client-spec.md#print-paper-size).
|
||||
- **Fits-the-page editing.** Fields that would overflow the printable sheet are rejected as you type, with an inline error under the affected field. See the [field length cheat sheet](docs/flyer-field-limits.md) for how much text fits each field per language and paper size.
|
||||
- **QR codes.** The tear-off QR points at the poster URL (re-open and reprint); the main flyer QR points at the creator's content URL.
|
||||
- **Bulletin board (members-only, trust-filtered).** A small screen-only link below the flyer preview (outside the printed sheet, never printed) opens a spreadsheet-style page of the most recent flyers found on the relays — title, link, posting npub, language, date, and event ID (with a copy button) — sortable by any column. Viewing the board requires connecting a Nostr identity — via a NIP-07 browser extension, by pasting a private key (`nsec`, decoded in-page and never stored), or by creating a new key (revealed so you can save it). The board then shows only flyers from authors in your **web of trust** (your NIP-02 follow graph), with a "Show all" opt-out. A brand-new key with no follows is seeded from a curated trust anchor so the board is never an unmoderated firehose. On your own flyers the board offers inline **Edit / Re-broadcast / Delete**; on others' it offers **Report** (a public, signed NIP-56 report with a category and optional reason, which also hides the flyer for you) and a local **Block** (a per-device hide list). Connecting is not required to author or print flyers, which stay fully anonymous. See the [roadmap](docs/roadmap.md) for the phased trust model.
|
||||
- **Mobile-friendly.** The flyer preview shrinks to fully fit the screen width (no side-scrolling), the editor and viewer are single-column with large tap targets, and the bulletin board collapses to a card per flyer with a per-row **Details** toggle on narrow screens.
|
||||
- **Honest safety page.** A localized **[Safety & privacy](https://voxvera.org/safety)** page (linked from the editor and board) explains in plain language what VoxVera protects and — just as importantly — what it does *not*: relays see your IP when you publish or browse, the anonymous key is stored unencrypted in your browser, a short PIN won't stop a targeted attacker, and published events are public and effectively permanent. Plus operational tips (Tor/VPN, disposable keys, signer apps). No overpromising to the people most likely to rely on it.
|
||||
- **Self-contained.** No build step and no CDNs — Nostr and QR libraries are vendored under `site/vendor/`.
|
||||
|
||||
Linux with systemd is the supported persistent-host deployment target.
|
||||
Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey remain experimental until their background Tor hosting and auto-recovery paths are validated end-to-end.
|
||||
## What Is In `main`
|
||||
|
||||
See [docs/platform-support-matrix.md](docs/platform-support-matrix.md) for the canonical platform status table and [docs/roadmap-platform-parity.md](docs/roadmap-platform-parity.md) for the parity plan.
|
||||
For the supported Linux hosting path, use [docs/linux-hosting-validation.md](docs/linux-hosting-validation.md) as the operational validation runbook.
|
||||
- `site/index.html`, `site/nostr-client.js`, `site/nostr-client.css`, `site/locales.js`: static editor/viewer client
|
||||
- `site/board.html`, `site/board.js`: bulletin-board page listing recent flyers from the relays
|
||||
- `site/vendor/`: vendored browser dependencies for Nostr and QR generation
|
||||
- `site/nostr/index.html`: redirect stub so legacy `/nostr/` poster URLs and QR codes still resolve
|
||||
- `site/CNAME`: custom-domain target
|
||||
- `voxvera/nostr/`: small Python schema/validation helpers
|
||||
- `docs/nostr-static-client-spec.md`: design notes and development plan
|
||||
- `docs/flyer-field-limits.md`: per-language field length cheat sheet
|
||||
- `docs/roadmap.md`: known issues and future development directions
|
||||
|
||||
### 1. Standalone Binaries (Recommended)
|
||||
Download the executable for your OS:
|
||||
- 🐧 [**Linux**](https://github.com/PR0M3TH3AN/VoxVera/releases/latest/download/voxvera-linux)
|
||||
- 🪟 [**Windows (Experimental)**](https://github.com/PR0M3TH3AN/VoxVera/releases/latest/download/voxvera-windows.exe)
|
||||
- 🍏 [**macOS (Experimental)**](https://github.com/PR0M3TH3AN/VoxVera/releases/latest/download/voxvera-macos)
|
||||
## Local Development
|
||||
|
||||
### 2. Universal Mirroring (The "Viral" Method)
|
||||
If you found a physical VoxVera flyer, scan it and click **"Download"**. You will receive a `voxvera-portable.zip` containing the full tool, all dependencies, and all 14 languages—ready to run offline.
|
||||
Run the static site from the repo root:
|
||||
|
||||
### 3. One-Line Installer (Linux/macOS)
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
On Linux, this now installs the recurring `systemd --user` recovery timer used to retry hidden-service startup after boot or offline periods. On macOS, the installer path is still experimental.
|
||||
|
||||
### 4. Developer / Python Install
|
||||
```bash
|
||||
pip install .
|
||||
voxvera vendorize # Optional: pull dependencies locally for offline use
|
||||
python3 -m http.server 8768 --directory site
|
||||
```
|
||||
|
||||
### 5. Local Validation
|
||||
Run the full local validation sweep with:
|
||||
```bash
|
||||
bash scripts/check.sh
|
||||
Then open:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:8768/
|
||||
```
|
||||
This runs linting, Python tests, Electron smoke tests, dependency checks, and the docs/site rebuild steps used during development.
|
||||
|
||||
---
|
||||
No build command is required for the frontend.
|
||||
|
||||
## Key Features
|
||||
## Vercel
|
||||
|
||||
* **Universal Mirroring**: Every flyer acts as a mirror for the tool itself. The "Download" button provides a portable version of VoxVera, creating a decentralized distribution network.
|
||||
* **Standalone Binaries**: Zero-install executables for high-security environments.
|
||||
* **Global Multi-Script Support**: Native support for 14 languages including **Arabic (RTL)**, **Hebrew (RTL)**, **Hindi (Devanagari)**, **Japanese/Chinese (CJK)**, and **Russian (Cyrillic)**.
|
||||
* **Tor-Safe Architecture**: 100% static HTML flyers. Works perfectly in Tor "Safest" mode with **JavaScript completely disabled**.
|
||||
* **Integrated Server Manager**: `voxvera manage` provides an interactive UI to handle multiple flyers, monitor Tor bootstrapping, and manage persistent .onion URLs.
|
||||
* **Secure Migration**: Bulk export and import of flyers and their unique Tor identity keys via `~/voxvera-exports/`.
|
||||
Point Vercel at this repository on `main`.
|
||||
|
||||
---
|
||||
- Framework preset: Other
|
||||
- Root directory: repo root
|
||||
- Build command: leave empty
|
||||
- Output directory: `site`
|
||||
|
||||
## Documentation
|
||||
The client is served from the domain root (`site/index.html`). `site/nostr/index.html` is a redirect stub that forwards the legacy `/nostr/` path to the root while preserving the query/fragment, so older poster URLs and printed QR codes still resolve.
|
||||
|
||||
VoxVera is available in multiple languages. Select your preferred language for the detailed usage guide:
|
||||
## Verification
|
||||
|
||||
| Language | Documentation | Contributing | Agent Guide |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| 🇺🇸 **English** | [usage.md](docs/en/usage.md) | [CONTRIBUTING.md](docs/en/CONTRIBUTING.md) | [AGENTS.md](docs/en/AGENTS.md) |
|
||||
| 🇪🇸 **Español** | [usage.md](docs/es/usage.md) | [CONTRIBUTING.md](docs/es/CONTRIBUTING.md) | [AGENTS.md](docs/es/AGENTS.md) |
|
||||
| 🇩🇪 **Deutsch** | [usage.md](docs/de/usage.md) | [CONTRIBUTING.md](docs/de/CONTRIBUTING.md) | [AGENTS.md](docs/de/AGENTS.md) |
|
||||
| 🇫🇷 **Français** | [usage.md](docs/fr/usage.md) | [CONTRIBUTING.md](docs/fr/CONTRIBUTING.md) | [AGENTS.md](docs/fr/AGENTS.md) |
|
||||
| 🇷🇺 **Русский** | [usage.md](docs/ru/usage.md) | [CONTRIBUTING.md](docs/ru/CONTRIBUTING.md) | [AGENTS.md](docs/ru/AGENTS.md) |
|
||||
| 🇮🇱 **עברית** | [usage.md](docs/he/usage.md) | [CONTRIBUTING.md](docs/he/CONTRIBUTING.md) | [AGENTS.md](docs/he/AGENTS.md) |
|
||||
| 🇸🇦 **العربية** | [usage.md](docs/ar/usage.md) | [CONTRIBUTING.md](docs/ar/CONTRIBUTING.md) | [AGENTS.md](docs/ar/AGENTS.md) |
|
||||
| 🇯🇵 **日本語** | [usage.md](docs/ja/usage.md) | [CONTRIBUTING.md](docs/ja/CONTRIBUTING.md) | [AGENTS.md](docs/ja/AGENTS.md) |
|
||||
| 🇮🇳 **हिन्दी** | [usage.md](docs/hi/usage.md) | [CONTRIBUTING.md](docs/hi/CONTRIBUTING.md) | [AGENTS.md](docs/hi/AGENTS.md) |
|
||||
| 🇰🇪 **Kiswahili** | [usage.md](docs/sw/usage.md) | [CONTRIBUTING.md](docs/sw/CONTRIBUTING.md) | [AGENTS.md](docs/sw/AGENTS.md) |
|
||||
```bash
|
||||
node --check site/nostr-client.js # client syntax
|
||||
pytest -q # Nostr source schema
|
||||
```
|
||||
|
||||
---
|
||||
### Cross-browser end-to-end tests
|
||||
|
||||
## Roadmap (v0.2.0)
|
||||
[Playwright](https://playwright.dev) smoke tests run the client on Chromium, Firefox, and WebKit (Safari's engine), plus Android/iOS mobile emulations — covering rendering, the `@media print` path, WebCrypto key generation, the `/nostr/` redirect, and the loading state.
|
||||
|
||||
We are actively working on:
|
||||
- **PGP Signing**: Cryptographic proof of tool integrity.
|
||||
- **Nostr Integration**: Automated social amplification.
|
||||
- **Template Gallery**: Visual styles for protests, alerts, and art.
|
||||
- **Self-Healing Network**: Automated decentralized updates.
|
||||
```bash
|
||||
npm install
|
||||
npx playwright install # download the browser engines
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
See [ROADMAP-v0.2.0.md](docs/roadmap-v0.2.0.md) for details.
|
||||
See [`e2e/README.md`](e2e/README.md) for per-engine coverage and the one-time Linux step for WebKit (`sudo npx playwright install-deps`).
|
||||
|
||||
---
|
||||
The Python tests only cover the Nostr source schema. The frontend is static; the Playwright suite covers engine behavior, but real Safari/iOS print and clipboard behavior is still worth a manual pass before a release.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
# VoxVera Release Process
|
||||
|
||||
**⚠️ ATTENTION AI AGENTS (CRITICAL WORKFLOW):**
|
||||
Do **NOT** automatically package, tag, or push a new release after completing a set of changes. Releases should **ONLY** be triggered when the user explicitly requests one (e.g., "Package a release now" or "Let's release this").
|
||||
Instead of releasing immediately, you must append a summary of your completed work to the `UPCOMING_RELEASE.md` file. This allows development to span multiple context sessions and ensures that new releases contain a substantial amount of value. When a release is finally requested, use the contents of `UPCOMING_RELEASE.md` to format the GitHub Release notes, and then clear the document for the next cycle.
|
||||
|
||||
This document outlines the mandatory steps to perform before every release to ensure code quality, cross-language integrity, and professional distribution assets.
|
||||
|
||||
## 1. Pre-Flight Checks (Quality Assurance)
|
||||
|
||||
Before any release, the codebase must pass all internal quality checks **without taking any shortcuts**. All tests must be rigorous, use real data where appropriate, and passing them should be a true mark of quality.
|
||||
|
||||
### Run Tests
|
||||
Ensure all core CLI, E2E, and Integrity tests pass:
|
||||
```bash
|
||||
pytest tests/
|
||||
```
|
||||
*Note: The `test_integrity.py` check is critical as it verifies that all 14+ language locales have synchronized keys and all binary bundles are 100% self-contained.*
|
||||
|
||||
### Run Linting
|
||||
Ensure the code adheres to style guidelines (no trailing whitespace, proper spacing, etc.):
|
||||
```bash
|
||||
# Using flake8 (excluding vendored dependencies)
|
||||
flake8 voxvera/ --exclude=voxvera/vendor/
|
||||
```
|
||||
|
||||
## 2. Update & Generate Localized Assets
|
||||
|
||||
Before releasing, you must ensure that **all documentation accurately reflects the new features and functions** introduced in the release.
|
||||
|
||||
All documentation and site templates must be synchronized with the translation system. This ensures that any changes to documentation are reflected across all 14+ supported languages.
|
||||
|
||||
### Synchronize Documentation
|
||||
If you have modified any documentation templates in `docs/templates/` (which you should, to cover new features), you **must** use the translation system to regenerate the localized documentation before release:
|
||||
```bash
|
||||
# Regenerate docs/ folders for all languages from templates and locales
|
||||
python3 -m voxvera.cli build-docs
|
||||
```
|
||||
|
||||
### Synchronize Site Assets
|
||||
The main `site/` directory (including QRs, HTML, and portable Zips) must also be refreshed to include the latest binary names and locale strings:
|
||||
```bash
|
||||
# Refresh site/ directory
|
||||
python3 -m voxvera.cli build-site
|
||||
```
|
||||
|
||||
## 3. Build Distribution Binaries
|
||||
|
||||
Linux CLI delivery is the supported deployment target today. Other package formats should be treated as experimental release artifacts until their Tor/OnionShare background-hosting behavior is validated end-to-end.
|
||||
Capture platform evidence before promoting any support tier: run `bash scripts/platform-smoke.sh linux-cli` locally for the supported Linux path, and keep CI/workflow evidence aligned with the same command.
|
||||
As other runtime targets mature, use `bash scripts/platform-smoke.sh macos-cli`, `bash scripts/platform-smoke.sh windows-cli`, or `bash scripts/platform-smoke.sh docker-cli` on their native environments before changing their support labels.
|
||||
|
||||
### Standard Binary
|
||||
Generates an architecture-specific binary (e.g., `voxvera-linux-x86_64`) in `voxvera/resources/bin/`.
|
||||
```bash
|
||||
./scripts/build_binaries.sh
|
||||
```
|
||||
This directory is local build output only. Do not treat old files in `voxvera/resources/bin/` as canonical release history; the GitHub Release artifacts are the publish surface.
|
||||
|
||||
### AppImage (Linux)
|
||||
Wraps the standard binary into a self-contained AppImage.
|
||||
```bash
|
||||
./packaging/build_appimage.sh
|
||||
```
|
||||
Experimental package surface.
|
||||
|
||||
### Flatpak (Linux)
|
||||
Generates a standalone `.flatpak` bundle. Requires `flatpak-builder`.
|
||||
```bash
|
||||
./packaging/build_flatpak.sh
|
||||
```
|
||||
Experimental package surface.
|
||||
|
||||
### Debian Package (Linux)
|
||||
Generates a `.deb` package for Debian/Ubuntu systems.
|
||||
```bash
|
||||
./packaging/build_deb.sh
|
||||
```
|
||||
Experimental package surface unless its runtime dependencies and recovery behavior are explicitly validated for the release.
|
||||
|
||||
### DMG (macOS)
|
||||
Generates a `.dmg` installer for macOS (must be run on macOS).
|
||||
```bash
|
||||
./packaging/build_dmg.sh
|
||||
```
|
||||
Experimental package surface.
|
||||
|
||||
## 4. Release Execution
|
||||
|
||||
1. **Version Bump:** Update `__version__` in `voxvera/__init__.py` and `version` in `pyproject.toml`.
|
||||
2. **Commit & Tag:**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "chore: release vX.Y.Z"
|
||||
git tag -a vX.Y.Z -m "VoxVera vX.Y.Z"
|
||||
git push origin main --tags
|
||||
```
|
||||
## 5. Automated Releases (GitHub Actions)
|
||||
|
||||
The repository is configured with a **Build Standalone Binaries** workflow that automatically runs when a new tag (`v*`) is pushed. This workflow:
|
||||
- Builds native executables for **Linux**, **Windows (.exe)**, and **macOS**.
|
||||
- Automatically attaches these binaries to the corresponding GitHub Release.
|
||||
|
||||
This ensures that Windows users receive a professional `voxvera-windows.exe` rather than having to rely on `.bat` or `.sh` scripts.
|
||||
@@ -1 +0,0 @@
|
||||
# Upcoming Release Notes
|
||||
-218
@@ -1,218 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Robustness: ensure we are in the project root
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
LOG_DIR="$(pwd)/ci-logs"
|
||||
mkdir -p "$LOG_DIR"
|
||||
# Use a subshell for tee to avoid issues with some shell environments
|
||||
exec > >(tee "$LOG_DIR/run.log") 2>&1
|
||||
|
||||
echo "Starting E2E verification at $(date)"
|
||||
|
||||
# Install VoxVera
|
||||
if [ -n "${VOXVERA_BIN:-}" ] && [ -f "$VOXVERA_BIN" ]; then
|
||||
voxvera_cmd="$VOXVERA_BIN"
|
||||
echo "Using provided VoxVera binary: $voxvera_cmd" >&2
|
||||
elif command -v voxvera >/dev/null 2>&1; then
|
||||
voxvera_cmd="$(command -v voxvera)"
|
||||
echo "Using existing VoxVera on PATH: $voxvera_cmd" >&2
|
||||
else
|
||||
echo "Installing VoxVera in editable mode..."
|
||||
python3 -m pip install --break-system-packages --no-build-isolation -e ".[e2e]"
|
||||
voxvera_cmd="$(command -v voxvera || echo "$HOME/.local/bin/voxvera")"
|
||||
fi
|
||||
|
||||
echo "VoxVera command: $voxvera_cmd"
|
||||
|
||||
echo "Checking platform contract before workflow..."
|
||||
bash scripts/platform-smoke.sh linux-cli
|
||||
|
||||
# Generate demo flyer
|
||||
echo "Initializing demo flyer..."
|
||||
"$voxvera_cmd" --lang en init --template voxvera <<EOI
|
||||
DemoUser
|
||||
voxvera
|
||||
EOI
|
||||
|
||||
config_path="$HOME/host/voxvera/config.json"
|
||||
if [ ! -f "$config_path" ]; then
|
||||
echo "CRITICAL: Expected config file not found after init: $config_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building demo flyer..."
|
||||
"$voxvera_cmd" --lang en --config "$config_path" build
|
||||
|
||||
# Verify build output exists in host/
|
||||
folder_name="voxvera"
|
||||
host_dir="$HOME/host/$folder_name"
|
||||
|
||||
if [ ! -d "$host_dir" ]; then
|
||||
echo "CRITICAL: Host directory $host_dir not found!" >&2
|
||||
ls -R "$HOME/host/" || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ls -R "$host_dir" >>"$LOG_DIR/tree.txt"
|
||||
|
||||
# Verify essential files
|
||||
for f in index.html config.json; do
|
||||
if [ ! -f "$host_dir/$f" ]; then
|
||||
echo "CRITICAL: Missing $f in $host_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Build output verified in $host_dir"
|
||||
|
||||
# Run pytest unit tests
|
||||
echo "Running pytest unit tests..."
|
||||
python3 -m pytest tests/ -v 2>&1 | tee "$LOG_DIR/pytest.log"
|
||||
|
||||
# Optional network tests
|
||||
if [ "${VOXVERA_E2E_OFFLINE:-}" != "1" ]; then
|
||||
echo "Starting network-dependent tests..."
|
||||
|
||||
# GitHub Actions Ubuntu runners have Tor pre-installed and running as a service.
|
||||
# We stop it to ensure we can run our own instance with known configuration on default ports.
|
||||
echo "Stopping system Tor service if running..."
|
||||
sudo systemctl stop tor || true
|
||||
|
||||
# Kill any lingering tor processes
|
||||
sudo pkill -x tor || true
|
||||
|
||||
echo "Starting a fresh Tor instance on default ports (9050/9051)..."
|
||||
mkdir -p "$LOG_DIR/tor_data"
|
||||
tor --SocksPort 9050 --ControlPort 9051 --CookieAuthentication 0 --DataDirectory "$LOG_DIR/tor_data" >"$LOG_DIR/tor.log" 2>&1 &
|
||||
TOR_PID=$!
|
||||
|
||||
# Wait for Tor to bootstrap
|
||||
echo "Waiting for Tor to bootstrap (up to 120s)..."
|
||||
BOOTSTRAPPED=0
|
||||
for i in {1..120}; do
|
||||
if grep -q "Bootstrapped 100%" "$LOG_DIR/tor.log"; then
|
||||
echo "Tor bootstrapped successfully."
|
||||
BOOTSTRAPPED=1
|
||||
break
|
||||
fi
|
||||
[ $((i % 10)) -eq 0 ] && echo "... still bootstrapping Tor ($i s) ..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ $BOOTSTRAPPED -eq 0 ]; then
|
||||
echo "CRITICAL: Tor failed to bootstrap after 120s" >&2
|
||||
tail -n 20 "$LOG_DIR/tor.log"
|
||||
kill ${TOR_PID:-} || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking platform contract with live Tor..."
|
||||
VOXVERA_REQUIRE_TOR=1 bash scripts/platform-smoke.sh linux-cli
|
||||
|
||||
# Start OnionShare
|
||||
echo "Starting OnionShare..."
|
||||
# Explicitly set environment variables that OnionShare-cli respects
|
||||
export TOR_SOCKS_PORT=9050
|
||||
export TOR_CONTROL_PORT=9051
|
||||
|
||||
onionshare-cli --website --public \
|
||||
--persistent "$host_dir/.onionshare-session" \
|
||||
-v \
|
||||
"$host_dir" >"$LOG_DIR/onionshare.log" 2>&1 &
|
||||
OS_PID=$!
|
||||
|
||||
# Check if OnionShare process is still alive after a few seconds
|
||||
sleep 5
|
||||
if ! kill -0 $OS_PID 2>/dev/null; then
|
||||
echo "CRITICAL: OnionShare-cli failed to start" >&2
|
||||
cat "$LOG_DIR/onionshare.log"
|
||||
kill ${TOR_PID:-} || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait for URL with timeout and feedback
|
||||
echo "Waiting for OnionShare to generate URL (up to 120s)..."
|
||||
URL=""
|
||||
for i in {1..120}; do
|
||||
# Use -a to process as text even if there are binary chars (ANSI codes)
|
||||
if grep -aEo 'http[s]?://[a-z2-7]{56}\.onion' "$LOG_DIR/onionshare.log" | head -n1 >"$LOG_DIR/url.txt"; then
|
||||
URL=$(cat "$LOG_DIR/url.txt" | tr -d '\r\n ')
|
||||
if [ -n "$URL" ]; then
|
||||
echo "Successfully generated Onion URL: $URL"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
[ $((i % 10)) -eq 0 ] && echo "... still waiting ($i s) ..."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ -z "$URL" ]; then
|
||||
echo "CRITICAL: Onion URL not found after 120s" >&2
|
||||
echo "--- Last 20 lines of OnionShare log ---"
|
||||
tail -n 20 "$LOG_DIR/onionshare.log"
|
||||
kill $OS_PID || true
|
||||
kill ${TOR_PID:-} || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Robustness: Manually update the config.json with the URL so verification passes
|
||||
# and the site is actually using the live onion address.
|
||||
echo "Updating $host_dir/config.json with live URL: $URL"
|
||||
python3 <<EOF
|
||||
import json
|
||||
import os
|
||||
path = "$host_dir/config.json"
|
||||
with open(path, 'r') as f:
|
||||
data = json.load(f)
|
||||
data['url'] = "$URL"
|
||||
with open(path + '.new', 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
os.replace(path + '.new', path)
|
||||
EOF
|
||||
|
||||
echo "Verifying content of $host_dir/config.json:"
|
||||
cat "$host_dir/config.json"
|
||||
|
||||
# Verify URL in config
|
||||
if ! grep -Fq "$URL" "$host_dir/config.json"; then
|
||||
echo "CRITICAL: URL $URL not found in $host_dir/config.json" >&2
|
||||
cat "$host_dir/config.json"
|
||||
kill $OS_PID || true
|
||||
kill ${TOR_PID:-} || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Re-build to update QR codes with live onion URL
|
||||
echo "Re-building site with live URL..."
|
||||
"$voxvera_cmd" --lang en build --config "$host_dir/config.json"
|
||||
|
||||
# Fetch page via Tor (retry a few times as circuits can be flaky)
|
||||
echo "Verifying reachability via Tor (on port 9050)..."
|
||||
FETCHED=0
|
||||
for attempt in {1..5}; do
|
||||
echo "Attempt $attempt..."
|
||||
if curl --socks5-hostname 127.0.0.1:9050 -fsSL "$URL" | grep -q '<title>'; then
|
||||
echo "Success: Site is reachable via Tor."
|
||||
FETCHED=1
|
||||
break
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
|
||||
if [ $FETCHED -eq 0 ]; then
|
||||
echo "WARNING: Site could not be reached via Tor after 5 attempts, but OnionShare is running."
|
||||
# In CI, we might skip hard failure if Tor network is exceptionally slow/blocked
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
echo "Cleaning up..."
|
||||
kill $OS_PID || true
|
||||
kill ${TOR_PID:-} || true
|
||||
wait $OS_PID 2>/dev/null || true
|
||||
else
|
||||
echo "Skipping network-dependent tests (VOXVERA_E2E_OFFLINE=1)" >&2
|
||||
fi
|
||||
|
||||
echo "E2E verification complete at $(date)"
|
||||
exit 0
|
||||
@@ -0,0 +1,18 @@
|
||||
# Data Center Construction Protest Demo Flyer
|
||||
|
||||
Use these values in the VoxVera editor for a civic protest or public-comment demo.
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Relays | `wss://relay.damus.io`, `wss://nos.lol`, `wss://relay.primal.net` |
|
||||
| Flyer Name | `data-center-protest` |
|
||||
| Language | `en` |
|
||||
| Page title | `Data Center Protest Flyer` |
|
||||
| Title | `PUBLIC HEARING` |
|
||||
| Subtitle | `NO BLANK CHECK FOR BIG TECH` |
|
||||
| Headline | `STOP THE DATA CENTER LAND GRAB` |
|
||||
| Content | `A proposed data center project could strain local power, water, roads, and public budgets while leaving residents with noise, traffic, and long-term infrastructure costs. Attend the public hearing, ask for full environmental review, and demand binding limits before any approval.` |
|
||||
| URL message | `Scan for meeting time, talking points, and public-comment instructions.` |
|
||||
| Content URL | `https://example.com/data-center-hearing` |
|
||||
| Footer message | `BRING NEIGHBORS - SPEAK DURING PUBLIC COMMENT` |
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Presbyterian Gospel Tract Demo Flyer
|
||||
|
||||
Use these values in the VoxVera editor for a Reformed Presbyterian gospel tract demo.
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Relays | `wss://relay.damus.io`, `wss://nos.lol`, `wss://relay.primal.net` |
|
||||
| Flyer Name | `presbyterian-gospel-tract` |
|
||||
| Language | `en` |
|
||||
| Page title | `Presbyterian Gospel Tract` |
|
||||
| Title | `CHRIST SAVES SINNERS` |
|
||||
| Subtitle | `REPENT AND BELIEVE THE GOSPEL` |
|
||||
| Headline | `THE GOOD NEWS OF JESUS CHRIST` |
|
||||
| Content | `God is holy, and all men have sinned against Him. Yet God sent His eternal Son, Jesus Christ, to take on true humanity, obey perfectly, die for sinners, and rise again. Salvation is by grace alone, through faith alone, in Christ alone. Turn from sin and trust the Lord Jesus Christ.` |
|
||||
| URL message | `Scan to read Scripture, a short catechism, and a local church invitation.` |
|
||||
| Content URL | `https://example.com/gospel` |
|
||||
| Footer message | `FOR BY GRACE ARE YE SAVED THROUGH FAITH - EPHESIANS 2:8` |
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Yard Sale Demo Flyer
|
||||
|
||||
Use these values in the VoxVera editor as a practical neighborhood-sale demo.
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Relays | `wss://relay.damus.io`, `wss://nos.lol`, `wss://relay.primal.net` |
|
||||
| Flyer Name | `yard-sale-saturday` |
|
||||
| Language | `en` |
|
||||
| Page title | `Saturday Yard Sale` |
|
||||
| Title | `YARD SALE` |
|
||||
| Subtitle | `SATURDAY 8 AM TO 2 PM` |
|
||||
| Headline | `TOOLS, BOOKS, TOYS, AND HOME GOODS` |
|
||||
| Content | `Stop by this Saturday for a family yard sale with useful household items, kids clothes, books, tools, small furniture, toys, and kitchen goods. Prices are marked to move. Cash is preferred, and early visitors are welcome after 8 AM.` |
|
||||
| URL message | `Scan for address, photos, and any weather updates.` |
|
||||
| Content URL | `https://example.com/yard-sale` |
|
||||
| Footer message | `SATURDAY ONLY - PLEASE PARK ALONG THE STREET` |
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# الاستخدام التفصيلي
|
||||
|
||||
يغطي هذا الدليل سير عمل واجهة سطر الأوامر (CLI) الشائعة. راجع `docs/docker.md` للحصول على تعليمات Docker و `docs/templates.md` لقوالب المنشورات المتاحة.
|
||||
|
||||
## المتطلبات الأساسية
|
||||
|
||||
تم تصميم VoxVera ليكون سهل النقل للغاية ويتطلب الحد الأدنى من تبعيات النظام.
|
||||
|
||||
### 1. الملفات الثنائية المستقلة (موصى به)
|
||||
يمكنك تنزيل ملفات ثنائية مستقلة بدون تبعيات لنظام التشغيل الخاص بك:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
تتضمن هذه الملفات الثنائية كل ما يلزم لتشغيل VoxVera (باستثناء `onionshare-cli`).
|
||||
|
||||
### 2. المثبت بنقرة واحدة
|
||||
بدلاً من ذلك، قم بالتثبيت عبر البرمجية النصية المؤتمتة الخاصة بنا:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. تثبيت Python اليدوي
|
||||
إذا كنت تفضل التشغيل من المصدر:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## خطوة بخطوة
|
||||
|
||||
1. **التهيئة:** قم بتشغيل `voxvera init` واتبع المطالبات. سيُطلب منك اختيار لغتك أولاً.
|
||||
2. **البناء:** قم بإنشاء أصول المنشور. ينشئ كل بناء تلقائياً ملف `voxvera-portable.zip` في مجلد المنشور، مما يسمح للآخرين بتنزيل الأداة الكاملة مباشرة من منشورك.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **الخدمة:** انشر المنشور عبر Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
يكتشف هذا تلقائياً نسخة Tor الخاصة بك، ويبدأ OnionShare، ويكتب عنوان .onion الناتج في روابط المنشور القابلة للنزع.
|
||||
|
||||
## دعم اللغة
|
||||
|
||||
VoxVera مترجم بالكامل. يمكنك تغيير تفضيل اللغة الخاص بك بشكل دائم باستخدام المبدل التفاعلي أو اختصار مباشر:
|
||||
|
||||
- **المبدل التفاعلي:** `voxvera lang`
|
||||
- **اختصار مباشر:** `voxvera --lang ar` (يضبط التفضيل على العربية)
|
||||
|
||||
### اللغات المدعومة:
|
||||
- **الإنجليزية:** `en`
|
||||
- **الإسبانية:** `es` (اسم مستعار: `--idioma`)
|
||||
- **الألمانية:** `de` (اسم مستعار: `--sprache`)
|
||||
- **العربية:** `ar`
|
||||
|
||||
يمكنك أيضاً فرض لغة معينة لأمر واحد دون تغيير تفضيلك الدائم:
|
||||
- **الإنجليزية:** `voxvera --lang en check`
|
||||
- **العربية:** `voxvera --lang ar check`
|
||||
|
||||
تكتشف المنشورات الناتجة تلقائياً لغة متصفح الزائر وتبدل نص واجهة المستخدم وفقاً لذلك.
|
||||
|
||||
## إدارة الخوادم
|
||||
|
||||
إدارة منشورات متعددة وهويات Tor الخاصة بها من قائمة تفاعلية واحدة:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
الميزات:
|
||||
- **--- إنشاء موقع/منشور جديد ---**: ابدأ تسلسل الإعداد الكامل.
|
||||
- **--- تشغيل جميع المواقع ---**: تشغيل أو إيقاف جميع المنشورات في أسطولك دفعة واحدة.
|
||||
- **الحالة في الوقت الفعلي**: عرض روابط .onion النشطة ومؤشرات تقدم تمهيد Tor.
|
||||
- **التحكم الفردي**: تصدير إلى Zip مواقع معينة إلى ZIP أو حذفها.
|
||||
|
||||
## مراجة شاملة (التوزيع الفيروسي)
|
||||
|
||||
لضمان بقاء VoxVera متاحاً حتى لو تم فرض رقابة على المستودعات المركزية، يعمل كل منشور كمرآة للأداة.
|
||||
|
||||
عندما تستضيف منشوراً، يوفر زر **"تحميل الأداة والكود"** في الصفحة المقصودة ملف `voxvera-portable.zip` يحتوي على:
|
||||
- كود المصدر الكامل وجميع اللغات المدعومة.
|
||||
- جميع تبعيات Python (مضمنة مسبقاً).
|
||||
- ملفات Tor الثنائية لجميع الأنظمة.
|
||||
|
||||
يتيح ذلك لأي شخص يقوم بمسح منشورك أن يصبح موزعاً جديداً لأداة VoxVera.
|
||||
|
||||
## التصدير والنسخ الاحتياطي
|
||||
|
||||
قم بنسخ هويات Tor الفريدة الخاصة بك احتياطياً (حتى لا يتغير رابط .onion الخاص بك أبداً) أو انقل منشوراتك إلى جهاز آخر.
|
||||
|
||||
- **تصدير موقع واحد**: `voxvera export <folder_name>`
|
||||
- **تصدير جميع المواقع**: `voxvera export-all`
|
||||
|
||||
**مكان التخزين:** يتم حفظ جميع الصادرات كملفات ZIP في مجلد يسمى `voxvera-exports` في دليل الصفحة الرئيسية للمستخدم (`~/voxvera-exports/`) على جميع الأنظمة.
|
||||
|
||||
## الاستيراد والاستعادة
|
||||
|
||||
استعد إعدادك بالكامل على جهاز جديد بنقل ملفات ZIP الخاصة بك إلى `~/voxvera-exports/` وتشغيل:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## النقل والتشغيل بدون إنترنت
|
||||
|
||||
إذا كنت بحاجة إلى تشغيل VoxVera على جهاز لا يتوفر فيه اتصال بالإنترنت، يمكنك "تضمين" التبعيات أولاً:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
يقوم هذا بتنزيل جميع مكتبات Python المطلوبة في `voxvera/vendor/`. ستعطي الأداة بعد ذلك الأولوية لهذه الملفات المحلية، مما يسمح لها بالعمل بدون `pip install`.
|
||||
|
||||
## استيراد جماعي (JSON)
|
||||
|
||||
لإنشاء منشورات بشكل جماعي من ملفات تكوين JSON متعددة، ضعها في مجلد `imports/` وشغل:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## كيف تعمل الروابط
|
||||
|
||||
يحتوي كل منشور على رابطين منفصلين:
|
||||
- **رابط قابل للنزع** (يتم إنشاؤه تلقائياً): عنوان .onion حيث يتم استضافة المنشور.
|
||||
- **رابط المحتوى** (يتم تكوينه بواسطة المستخدم): URL خارجي يشير إلى موقع ويب أو فيديو أو تنزيل.
|
||||
|
||||
لا تحتاج إلى إدخال عنوان .onion يدوياً؛ يتولى VoxVera ذلك تلقائياً خلال مرحلة `serve`.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,136 +0,0 @@
|
||||
# Detaillierte Verwendung
|
||||
|
||||
Diese Anleitung deckt gängige CLI-Workflows ab. Informationen zu Docker finden Sie unter `docs/docker.md` und verfügbare Flyer-Vorlagen unter `docs/templates.md`.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
VoxVera ist auf hohe Portabilität ausgelegt und erfordert minimale Systemabhängigkeiten.
|
||||
|
||||
### 1. Eigenständige Binärdateien (Empfohlen)
|
||||
Sie können eigenständige Binärdateien ohne Abhängigkeiten für Ihr Betriebssystem herunterladen:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
Diese Binärdateien enthalten alles, was zum Ausführen von VoxVera erforderlich ist (außer `onionshare-cli`).
|
||||
|
||||
### 2. Ein-Zeilen-Installer
|
||||
Alternativ können Sie die Installation über unser automatisiertes Skript vornehmen:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. Manuelle Python-Installation
|
||||
Wenn Sie lieber aus dem Quellcode ausführen möchten:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## Schritt für Schritt
|
||||
|
||||
1. **Initialisieren:** Führen Sie `voxvera init` aus und folgen Sie den Anweisungen. Sie werden zuerst aufgefordert, Ihre Sprache auszuwählen.
|
||||
2. **Bauen:** Erstellen Sie die Flyer-Assets. Jeder Build erstellt automatisch eine `voxvera-portable.zip` im Flyer-Ordner, sodass andere das komplette Tool direkt von Ihrem Flyer herunterladen können.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Bereitstellen:** Veröffentlichen Sie den Flyer über Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
Dies erkennt automatisch Ihre Tor-Instanz, startet OnionShare und schreibt die generierte .onion-Adresse in die Abreiß-Links des Flyers.
|
||||
|
||||
## Sprachunterstützung
|
||||
|
||||
VoxVera ist vollständig lokalisiert. Sie können Ihre Sprachpräferenz dauerhaft über den interaktiven Selektor oder eine direkte Verknüpfung ändern:
|
||||
|
||||
- **Interaktiver Selektor:** `voxvera lang`
|
||||
- **Direkte Verknüpfung:** `voxvera --lang de` (setzt die Präferenz auf Deutsch)
|
||||
|
||||
### Unterstützte Sprachen:
|
||||
- **Englisch:** `en`
|
||||
- **Spanisch:** `es` (Alias: `--idioma`)
|
||||
- **Deutsch:** `de` (Alias: `--sprache`)
|
||||
- **Russisch:** `ru`
|
||||
- **Hebräisch:** `he`
|
||||
- **Arabisch:** `ar`
|
||||
- **Französisch:** `fr`
|
||||
- **Japanisch:** `ja`
|
||||
- **Hindi:** `hi`
|
||||
- **Suaheli:** `sw`
|
||||
|
||||
Sie können auch eine bestimmte Sprache für einen einzelnen Befehl erzwingen, ohne Ihre dauerhafte Präferenz zu ändern:
|
||||
- **Englisch:** `voxvera --lang en check`
|
||||
- **Deutsch:** `voxvera --sprache de check`
|
||||
|
||||
Die generierten Flyer erkennen automatisch die Browsersprache des Besuchers und schalten den UI-Text entsprechend um.
|
||||
|
||||
## Server-Verwaltung
|
||||
|
||||
Verwalten Sie mehrere Flyer und deren Tor-Identitäten über ein einziges interaktives Menü:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Funktionen:
|
||||
- **--- Neue Website/Flyer erstellen ---**: Starten Sie die vollständige Setup-Sequenz.
|
||||
- **--- Alle Websites starten ---**: Starten oder stoppen Sie alle Flyer in Ihrer Flotte auf einmal.
|
||||
- **Echtzeit-Status**: Zeigen Sie aktive .onion-URLs und Tor-Bootstrapping-Fortschrittsanzeigen an.
|
||||
- **Individuelle Steuerung**: Als Zip exportieren Sie bestimmte Seiten in eine ZIP-Datei oder löschen Sie sie.
|
||||
|
||||
## Universelle Spiegelung (Virale Verteilung)
|
||||
|
||||
Um sicherzustellen, dass VoxVera auch dann zugänglich bleibt, wenn zentrale Repositories zensiert werden, fungiert jeder Flyer als Spiegel für das Tool.
|
||||
|
||||
Wenn Sie einen Flyer hosten, bietet die Schaltfläche **"Tool & Quellcode herunterladen"** auf der Landingpage eine `voxvera-portable.zip` an, die Folgendes enthält:
|
||||
- Den vollständigen Quellcode und alle unterstützten Sprachen.
|
||||
- Alle Python-Abhängigkeiten (vorinstalliert).
|
||||
- Plattformübergreifende Tor-Binärdateien.
|
||||
|
||||
Dies ermöglicht es jedem, der Ihren Flyer scannt, ein neuer Distributor des VoxVera-Tools zu werden.
|
||||
|
||||
## Export & Sicherung
|
||||
|
||||
Sichern Sie Ihre eindeutigen Tor-Identitäten (damit sich Ihre .onion-URL nie ändert) oder verschieben Sie Ihre Flyer auf einen anderen Computer.
|
||||
|
||||
- **Einzelne Seite exportieren:** `voxvera export <folder_name>`
|
||||
- **Alle Seiten exportieren:** `voxvera export-all`
|
||||
|
||||
**Speicherort:** Alle Exporte werden als ZIP-Dateien in einem Ordner namens `voxvera-exports` im Home-Verzeichnis des Benutzers (`~/voxvera-exports/`) auf allen Plattformen gespeichert.
|
||||
|
||||
## Import & Wiederherstellung
|
||||
|
||||
Stellen Sie Ihr gesamtes Setup auf einem neuen Computer wieder her, indem Sie Ihre ZIP-Dateien nach `~/voxvera-exports/` verschieben und Folgendes ausführen:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Portabilität & Offline-Nutzung
|
||||
|
||||
Wenn Sie VoxVera auf einem Computer ohne Internetzugang ausführen müssen, können Sie die Abhängigkeiten zuerst lokal bereitstellen:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
Dies lädt alle erforderlichen Python-Bibliotheken in `voxvera/vendor/` herunter. Das Tool priorisiert dann diese lokalen Dateien, sodass es ohne `pip install` ausgeführt werden kann.
|
||||
|
||||
## Batch-Import (JSON)
|
||||
|
||||
Um Flyer in großen Mengen aus mehreren JSON-Konfigurationsdateien zu generieren, legen Sie diese im Verzeichnis `imports/` ab und führen Sie Folgendes aus:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## Wie URLs funktionieren
|
||||
|
||||
Jeder Flyer hat zwei separate URLs:
|
||||
- **Abreiß-Link** (automatisch generiert): Die .onion-Adresse, unter der der Flyer gehostet wird.
|
||||
- **Inhalts-Link** (vom Benutzer konfiguriert): Eine externe URL, die auf eine Website, ein Video oder einen Download verweist.
|
||||
|
||||
Sie müssen die .onion-Adresse nicht manuell eingeben; VoxVera erledigt dies automatisch während der `serve`-Phase.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,152 +0,0 @@
|
||||
# Detailed Usage
|
||||
|
||||
This guide covers common CLI workflows. See `docs/docker.md` for Docker instructions and `docs/templates.md` for available flyer templates.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
VoxVera is designed to be highly portable. You can run it directly from the source code on any platform with Python installed.
|
||||
|
||||
Linux with `systemd --user` is the supported persistent-host environment. Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and should not yet be treated as equally reliable hidden-service deployment targets.
|
||||
|
||||
### 1. Automated Install (Recommended)
|
||||
The easiest way to install VoxVera is using the Linux-first installer script:
|
||||
|
||||
**Linux / macOS:**
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
On Linux, this also installs the recurring recovery timer used to retry hidden-service startup after boot and after missed/offline periods.
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
irm https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.ps1 | iex
|
||||
```
|
||||
The Windows installer is experimental and does not yet guarantee production-ready background hosting behavior.
|
||||
|
||||
### 2. Manual Source Install
|
||||
If you have downloaded the source code ZIP:
|
||||
|
||||
1. **Extract** the ZIP file.
|
||||
2. **Open a terminal** in the extracted folder.
|
||||
3. **Run the setup script**:
|
||||
- **Linux/macOS:** `./setup.sh`
|
||||
- **Windows:** `.\voxvera-install.sh` (or run `python -m pip install .`)
|
||||
|
||||
## Uninstallation
|
||||
|
||||
If you wish to remove VoxVera from your system, you can use the provided uninstall scripts from the source directory. This will safely remove the CLI tool and any downloaded dependencies.
|
||||
|
||||
- **Linux / macOS:** Run `./uninstall.sh`
|
||||
- **Windows (PowerShell):** Run `.\uninstall.ps1`
|
||||
|
||||
*Note: Uninstallation will not delete your generated flyers or your `.onion` keys stored in the `~/voxvera-exports` or local `host/` folders.*
|
||||
|
||||
## Step-by-Step
|
||||
|
||||
1. **Initialize:** Run `voxvera init` and follow the prompts. You will be asked to select your language first.
|
||||
2. **Build:** Generate the flyer assets. Every build automatically creates a `voxvera-portable.zip` in the flyer's folder, allowing others to download the full tool directly from your flyer.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Serve:** Publish the flyer over Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
This automatically detects your Tor instance, starts OnionShare, and writes the generated .onion address into the flyer's tear-off links.
|
||||
|
||||
### Persistent Hosting On Linux
|
||||
|
||||
For a machine that should resume hosting automatically after boot or after being offline, install the autostart recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
```
|
||||
|
||||
This installs a `systemd --user` timer that reruns `voxvera start-all` every few minutes. The retry loop is the supported way to recover hidden-service hosting after suspend, reboot, or temporary network loss.
|
||||
|
||||
## Language Support
|
||||
|
||||
VoxVera is fully localized. You can change your language preference permanently using either the interactive selector or a direct shortcut:
|
||||
|
||||
- **Interactive Selector:** `voxvera lang`
|
||||
- **Direct Shortcut:** `voxvera --lang de` (sets preference to German)
|
||||
|
||||
### Supported Languages:
|
||||
- **English:** `en`
|
||||
- **Spanish:** `es` (alias: `--idioma`)
|
||||
- **German:** `de` (alias: `--sprache`)
|
||||
|
||||
You can also force a specific language for a single command without changing your permanent preference:
|
||||
- **English:** `voxvera --lang en check`
|
||||
- **German:** `voxvera --sprache de check`
|
||||
- **Spanish:** `voxvera --idioma es check`
|
||||
|
||||
The generated flyers automatically detect the visitor's browser language and switch the UI text accordingly.
|
||||
|
||||
## Server Management
|
||||
|
||||
Manage multiple flyers and their Tor identities from a single interactive menu:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Features:
|
||||
- **--- Create New Site/Flyer ---**: Start the full setup sequence.
|
||||
- **--- Start All Sites ---**: Launch or shut down every flyer in your fleet at once.
|
||||
- **Real-time Status**: View active `.onion` URLs and Tor bootstrapping progress indicators.
|
||||
- **Individual Control**: Export to Zip specific sites to ZIP or delete them.
|
||||
|
||||
## Universal Mirroring (Viral Distribution)
|
||||
|
||||
To ensure VoxVera remains accessible even if central repositories are censored, every flyer acts as a mirror for the tool.
|
||||
|
||||
When you host a flyer, the **"Download Source Code"** button on the landing page provides a `voxvera-source.zip` containing:
|
||||
- The full source code and all supported languages.
|
||||
- Installation and setup scripts for all platforms.
|
||||
- Complete documentation and templates.
|
||||
|
||||
This allows anyone who scans your flyer to become a new distributor of the VoxVera tool.
|
||||
|
||||
## Export & Backup
|
||||
|
||||
Back up your unique Tor identities (so your `.onion` URL never changes) or move your flyers to another machine.
|
||||
|
||||
- **Export a single site**: `voxvera export <folder_name>`
|
||||
- **Export all sites**: `voxvera export-all`
|
||||
|
||||
**Storage location:** All exports are saved to `~/voxvera-exports/` on all platforms.
|
||||
|
||||
## Import & Recovery
|
||||
|
||||
Restore your entire setup on a new machine by moving your ZIP files to `~/voxvera-exports/` and running:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Portability & Offline Use
|
||||
|
||||
If you need to run VoxVera on a machine without internet access, you can "vendorize" the dependencies first:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
This downloads all required Python libraries into `voxvera/vendor/`. The tool will then prioritize these local files, allowing it to run without `pip install`.
|
||||
|
||||
## Batch Import (JSON)
|
||||
|
||||
To bulk-generate flyers from multiple JSON configuration files, place them in the `imports/` directory and run:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## How URLs Work
|
||||
|
||||
Each flyer has two separate URLs:
|
||||
- **Tear-off link** (auto-generated): The .onion address where the flyer is hosted.
|
||||
- **Content link** (user-configured): An external URL pointing to a website, video, or download.
|
||||
|
||||
You do not need to manually enter the .onion address; VoxVera handles this automatically during the `serve` phase.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,136 +0,0 @@
|
||||
# Uso detallado
|
||||
|
||||
Esta guía cubre los flujos de trabajo de CLI comunes. Consulte `docs/docker.md` para obtener instrucciones de Docker y `docs/templates.md` para conocer las plantillas de volantes disponibles.
|
||||
|
||||
## Prerrequisitos
|
||||
|
||||
VoxVera está diseñado para ser altamente portátil y requiere un mínimo de dependencias del sistema.
|
||||
|
||||
### 1. Binarios independientes (Recomendado)
|
||||
Puede descargar binarios independientes sin dependencias para su sistema operativo:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
Estos binarios incluyen todo lo necesario para ejecutar VoxVera (excepto `onionshare-cli`).
|
||||
|
||||
### 2. Instalador de una sola línea
|
||||
Alternativamente, instale a través de nuestro script automatizado:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. Instalación manual de Python
|
||||
Si prefiere ejecutar desde la fuente:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## Paso a paso
|
||||
|
||||
1. **Inicializar:** Ejecute `voxvera init` y siga las instrucciones. Se le pedirá que seleccione su idioma primero.
|
||||
2. **Construir:** Genere los activos del volante. Cada construcción crea automáticamente un `voxvera-portable.zip` en la carpeta del volante, lo que permite que otros descarguen la herramienta completa directamente desde su volante.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Servir:** Publique el volante sobre Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
Esto detecta automáticamente su instancia de Tor, inicia OnionShare y escribe la dirección .onion generada en los enlaces desprendibles del volante.
|
||||
|
||||
## Soporte de idiomas
|
||||
|
||||
VoxVera está totalmente localizado. Puede cambiar su preferencia de idioma de forma permanente utilizando el selector interactivo o un acceso directo:
|
||||
|
||||
- **Selector interactivo:** `voxvera lang`
|
||||
- **Acceso directo:** `voxvera --lang es` (establece la preferencia en español)
|
||||
|
||||
### Idiomas soportados:
|
||||
- **Inglés:** `en`
|
||||
- **Español:** `es` (alias: `--idioma`)
|
||||
- **Alemán:** `de` (alias: `--sprache`)
|
||||
- **Ruso:** `ru`
|
||||
- **Hebreo:** `he`
|
||||
- **Árabe:** `ar`
|
||||
- **Francés:** `fr`
|
||||
- **Japonés:** `ja`
|
||||
- **Hindi:** `hi`
|
||||
- **Swahili:** `sw`
|
||||
|
||||
También puede forzar un idioma específico para un solo comando sin cambiar su preferencia permanente:
|
||||
- **Inglés:** `voxvera --lang en check`
|
||||
- **Español:** `voxvera --idioma es check`
|
||||
|
||||
Los volantes generados detectan automáticamente el idioma del navegador del visitante y cambian el texto de la interfaz en consecuencia.
|
||||
|
||||
## Gestión de servidores
|
||||
|
||||
Gestione múltiples volantes y sus identidades de Tor desde un único menú interactivo:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Características:
|
||||
- **--- Crear Nuevo Sitio/Volante ---**: Inicie la secuencia de configuración completa.
|
||||
- **--- Iniciar Todos los Sitios ---**: Inicie o apague todos los volantes de su flota a la vez.
|
||||
- **Estado en tiempo real**: Vea las URL .onion activas e indicadores de progreso de arranque de Tor.
|
||||
- **Control individual**: Exportar a Zip sitios específicos a ZIP o elimínelos.
|
||||
|
||||
## Espejo universal (Distribución viral)
|
||||
|
||||
Para garantizar que VoxVera siga siendo accesible incluso si los repositorios centrales son censurados, cada volante actúa como un espejo para la herramienta.
|
||||
|
||||
Cuando hospeda un volante, el botón **"Descargar Herramienta y Código"** en la página de inicio proporciona un `voxvera-portable.zip` que contiene:
|
||||
- El código fuente completo y todos los idiomas soportados.
|
||||
- Todas las dependencias de Python (pre-vendeurizadas).
|
||||
- Binarios de Tor multiplataforma.
|
||||
|
||||
Esto permite que cualquier persona que escanee su volante se convierta en un nuevo distribuidor de la herramienta VoxVera.
|
||||
|
||||
## Exportación y respaldo
|
||||
|
||||
Haga una copia de seguridad de sus identidades únicas de Tor (para que su URL .onion nunca cambie) o mueva sus volantes a otra máquina.
|
||||
|
||||
- **Exportar un solo sitio**: `voxvera export <nombre_carpeta>`
|
||||
- **Exportar todos los servicios**: `voxvera export-all`
|
||||
|
||||
**Lugar de almacenamiento:** Todas las exportaciones se guardan como archivos ZIP en una carpeta llamada `voxvera-exports` en el directorio de inicio del usuario (`~/voxvera-exports/`) en todas las plataformas.
|
||||
|
||||
## Importación y recuperación
|
||||
|
||||
Restaure toda su configuración en una nueva máquina moviendo sus archivos ZIP a `~/voxvera-exports/` y ejecutando:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Portabilidad y uso sin conexión
|
||||
|
||||
Si necesita ejecutar VoxVera en una máquina sin acceso a Internet, primero puede "vendeurizar" las dependencias:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
Esto descarga todas las librerías de Python requeridas en `voxvera/vendor/`. La herramienta dará prioridad a estos archivos locales, lo que le permitirá ejecutarse sin `pip install`.
|
||||
|
||||
## Importación por lotes (JSON)
|
||||
|
||||
Para generar volantes de forma masiva a partir de múltiples archivos de configuración JSON, colóquelos en el directorio `imports/` y ejecute:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## Cómo funcionan las URL
|
||||
|
||||
Cada volante tiene dos URL separadas:
|
||||
- **Enlace desprendible** (generado automáticamente): La dirección .onion donde se hospeda el volante.
|
||||
- **Enlace de contenido** (configurado por el usuario): Una URL externa que apunta a un sitio web, video o descarga.
|
||||
|
||||
No es necesario ingresar manualmente la dirección .onion; VoxVera lo maneja automáticamente durante la fase de `serve`.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# راهنمای استفاده تفصیلی
|
||||
|
||||
این راهنما جریانهای کاری معمول رابط سطر فرمان (CLI) را پوشش میدهد. برای دستورالعملهای داکر به `docs/docker.md` و برای قالبهای اعلامیه موجود به `docs/templates.md` مراجعه کنید.
|
||||
|
||||
## پیشنیازها
|
||||
|
||||
ووکسورا (VoxVera) به گونهای طراحی شده است که بسیار قابل حمل باشد و به حداقل وابستگیهای سیستم نیاز داشته باشد.
|
||||
|
||||
### ۱. فایلهای اجرایی مستقل (توصیه شده)
|
||||
میتوانید فایلهای اجرایی (Binary) مستقل و بدون نیاز به وابستگی را برای سیستمعامل خود دانلود کنید:
|
||||
- **لینوکس:** `voxvera-linux`
|
||||
- **ویندوز:** `voxvera-windows.exe`
|
||||
- **مک:** `voxvera-macos`
|
||||
|
||||
این فایلها شامل تمام موارد لازم برای اجرای ووکسورا هستند (به جز `onionshare-cli`).
|
||||
|
||||
### ۲. نصبکننده تکخطی
|
||||
همچنین میتوانید از طریق اسکریپت خودکار ما نصب را انجام دهید:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### ۳. نصب دستی پایتون
|
||||
اگر ترجیح میدهید از سورس کد استفاده کنید:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # دبیان/اوبونتو
|
||||
```
|
||||
|
||||
## گام به گام
|
||||
|
||||
۱. **راهاندازی:** دستور `voxvera init` را اجرا کرده و مراحل را دنبال کنید. در ابتدا از شما خواسته میشود زبان خود را انتخاب کنید.
|
||||
۲. **ساخت:** داراییهای اعلامیه را ایجاد کنید. هر بار که عملیات ساخت انجام میشود، یک فایل `voxvera-portable.zip` به طور خودکار در پوشه اعلامیه ساخته میشود که به دیگران اجازه میدهد ابزار کامل را مستقیماً از اعلامیه شما دانلود کنند.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
۳. **میزبانی:** اعلامیه را روی شبکه تور منتشر کنید:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
این دستور به طور خودکار تور شما را شناسایی کرده، OnionShare را راهاندازی میکند و آدرس .onion تولید شده را در پیوندهای جداشونده اعلامیه مینویسد.
|
||||
|
||||
## پشتیبانی از زبانها
|
||||
|
||||
ووکسورا کاملاً بومیسازی شده است. میتوانید اولویت زبان خود را به طور دائم با استفاده از انتخابگر تعاملی یا میانبر مستقیم تغییر دهید:
|
||||
|
||||
- **انتخابگر تعاملی:** `voxvera lang`
|
||||
- **میانبر مستقیم:** `voxvera --lang fa` (تنظیم اولویت روی فارسی)
|
||||
|
||||
### زبانهای پشتیبانی شده:
|
||||
- **انگلیسی:** `en`
|
||||
- **اسپانیایی:** `es` (نام مستعار: `--idioma`)
|
||||
- **آلمانی:** `de` (نام مستعار: `--sprache`)
|
||||
- **فارسی:** `fa`
|
||||
|
||||
همچنین میتوانید بدون تغییر اولویت دائمی، یک زبان خاص را برای یک دستور واحد اجبار کنید:
|
||||
- **انگلیسی:** `voxvera --lang en check`
|
||||
- **فارسی:** `voxvera --lang fa check`
|
||||
|
||||
اعلامیههای تولید شده به طور خودکار زبان مرورگر بازدیدکننده را تشخیص داده و متن رابط کاربری را بر اساس آن تغییر میدهند.
|
||||
|
||||
## مدیریت سرورها
|
||||
|
||||
چندین اعلامیه و هویتهای تور آنها را از یک منوی تعاملی واحد مدیریت کنید:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
ویژگیها:
|
||||
- **--- ایجاد سایت/اعلامیه جدید ---**: شروع توالی کامل تنظیمات.
|
||||
- **--- اجرای همه سایتها ---**: راهاندازی یا توقف همزمان تمام اعلامیههای شما.
|
||||
- **وضعیت لحظهای**: مشاهده آدرسهای .onion فعال و نشانگرهای پیشرفت تور.
|
||||
- **کنترل فردی**: صدور به صورت زیپ سایتهای خاص به فرمت ZIP یا حذف آنها.
|
||||
|
||||
## آینهسازی همگانی (توزیع ویروسی)
|
||||
|
||||
برای اطمینان از اینکه ووکسورا حتی در صورت سانسور مخازن مرکزی در دسترس باقی میماند، هر اعلامیه به عنوان یک آینه برای این ابزار عمل میکند.
|
||||
|
||||
وقتی اعلامیهای را میزبانی میکنید، دکمه **"دانلود ابزار و کد منبع"** در صفحه فرود، یک فایل `voxvera-portable.zip` شامل موارد زیر ارائه میدهد:
|
||||
- سورس کد کامل و تمامی زبانهای پشتیبانی شده.
|
||||
- تمامی وابستگیهای پایتون (از پیش بستهبندی شده).
|
||||
- فایلهای اجرایی تور برای تمامی پلتفرمها.
|
||||
|
||||
این کار به هر کسی که اعلامیه شما را اسکن میکند اجازه میدهد تا به توزیعکننده جدیدی برای ابزار ووکسورا تبدیل شود.
|
||||
|
||||
## صدور و پشتیبانگیری
|
||||
|
||||
از هویتهای تور منحصر به فرد خود پشتیبان بگیرید (تا آدرس .onion شما هرگز تغییر نکند) یا اعلامیههای خود را به سیستم دیگری منتقل کنید.
|
||||
|
||||
- **صدور یک سایت واحد:** `voxvera export <folder_name>`
|
||||
- **صدور تمامی سایتها:** `voxvera export-all`
|
||||
|
||||
**محل ذخیرهسازی:** تمامی موارد صادر شده به صورت فایل ZIP در پوشهای به نام `voxvera-exports` در پوشه خانگی کاربر (`~/voxvera-exports/`) در تمامی پلتفرمها ذخیره میشوند.
|
||||
|
||||
## وارد کردن و بازیابی
|
||||
|
||||
با انتقال فایلهای ZIP خود به پوشه `~/voxvera-exports/` و اجرای دستور زیر، کل تنظیمات خود را در یک سیستم جدید بازیابی کنید:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## قابلیت حمل و استفاده آفلاین
|
||||
|
||||
اگر نیاز دارید ووکسورا را روی سیستمی بدون دسترسی به اینترنت اجرا کنید، میتوانید ابتدا وابستگیها را به صورت محلی ذخیره کنید:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
این دستور تمامی کتابخانههای پایتون مورد نیاز را در پوشه `voxvera/vendor/` دانلود میکند. ابزار سپس این فایلهای محلی را در اولویت قرار میدهد و اجازه میدهد بدون نیاز به `pip install` اجرا شود.
|
||||
|
||||
## وارد کردن گروهی (JSON)
|
||||
|
||||
برای تولید انبوه اعلامیهها از چندین فایل تنظیمات JSON، آنها را در پوشه `imports/` قرار داده و اجرا کنید:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## آدرسهای URL چگونه کار میکنند
|
||||
|
||||
هر اعلامیه دارای دو آدرس URL جداگانه است:
|
||||
- **پیوند جداشونده** (تولید خودکار): آدرس .onion که اعلامیه در آن میزبانی میشود.
|
||||
- **پیوند محتوا** (تنظیم توسط کاربر): یک آدرس URL خارجی که به یک وبسایت، ویدیو یا فایل دانلود اشاره میکند.
|
||||
|
||||
نیازی نیست آدرس .onion را به صورت دستی وارد کنید؛ ووکسورا در مرحله میزبانی (`serve`) این کار را به طور خودکار انجام میدهد.
|
||||
@@ -0,0 +1,74 @@
|
||||
# Flyer Field Length Cheat Sheet
|
||||
|
||||
How much text fits in each flyer field, by script.
|
||||
|
||||
VoxVera does **not** impose a fixed character count. The editor measures the
|
||||
rendered flyer live and rejects a keystroke the moment a field would overflow
|
||||
the printable sheet (you'll see an inline "too long" error under that field).
|
||||
So the real limit is enforced for you as you type — the numbers below are
|
||||
practical guidance for drafting copy, sizing translations, or prompting an LLM
|
||||
to write flyer text that will fit on the first try.
|
||||
|
||||
Capacity varies by **script** (not by individual language) and by **paper
|
||||
size**, for these reasons:
|
||||
|
||||
1. The flyer body font is monospace (`Courier New`), so within a script every
|
||||
character takes the same width regardless of upper/lowercase.
|
||||
2. Per-script letter-spacing policy (`ls-full` / `ls-cjk` / `ls-none`, see
|
||||
[`nostr-static-client-spec.md`](nostr-static-client-spec.md#letter-spacing-by-script)).
|
||||
3. Glyph width differs by script — CJK glyphs are full-width (≈2× a Latin
|
||||
character), Devanagari fallback glyphs are narrower, etc.
|
||||
4. **Paper size.** A4 (210×297mm) is slightly narrower and taller than US
|
||||
Letter (8.5×11in), so single-line fields hold ~2 fewer characters on A4
|
||||
while the body holds a little more. Both sizes are shown below.
|
||||
|
||||
## Single-line fields (hard caps)
|
||||
|
||||
**Title**, **Subtitle**, and **Headline** are single-line: they never wrap, so
|
||||
these are the limits people actually run into. Counts are characters
|
||||
(codepoints), shown as **Letter / A4**.
|
||||
|
||||
| Languages | Title & Headline | Subtitle |
|
||||
|---|---|---|
|
||||
| Latin & Cyrillic & Hebrew — en, es, de, fr, pt, sw, tr, ru, he | ~28 / ~26 | ~32 / ~30 |
|
||||
| Arabic & Persian — ar, fa | ~28 / ~27 | ~38 / ~36 |
|
||||
| Devanagari — hi | ~36 / ~35 | ~51 / ~48 |
|
||||
| CJK — ja, zh | ~17 / ~16 | ~23 / ~21 |
|
||||
|
||||
## Multi-line fields (generous)
|
||||
|
||||
**Body** (content), **Link message** (`url_message`), and **Footer**
|
||||
(`footer_message`) wrap across multiple lines, so they hold far more and are
|
||||
bounded only by the remaining height of the sheet.
|
||||
|
||||
| Languages | Body (content) — Letter / A4 |
|
||||
|---|---|
|
||||
| Latin & Cyrillic & Hebrew | ~1,900 / ~2,000 (a few hundred words) |
|
||||
| Arabic & Persian | ~1,850 / ~1,930 |
|
||||
| Devanagari — hi | ~2,450 / ~2,545 |
|
||||
| CJK — ja, zh | ~1,170 / ~1,220 |
|
||||
|
||||
`url_message` and `footer_message` share the lower portion of the sheet and can
|
||||
hold roughly 1,200–4,800 characters depending on script, but for a readable
|
||||
flyer keep the link message to a sentence and the footer to a short line.
|
||||
|
||||
The **URL** field is a link, not body copy — keep it short both because it's
|
||||
shown verbatim on the flyer and because it becomes the main QR code (shorter
|
||||
URLs scan more reliably).
|
||||
|
||||
## Notes and caveats
|
||||
|
||||
- **Approximate.** These come from rendering each script in a headless browser
|
||||
at true print size for both Letter (8.5×11in) and A4 (210×297mm). The
|
||||
Latin/Cyrillic numbers (`Courier New`) are the most reliable; numbers for
|
||||
Hebrew, Arabic, Persian, Devanagari, and CJK depend on the system fallback
|
||||
font, which can differ slightly between devices and from print output.
|
||||
- **The app is authoritative.** If the editor accepts your text it fits; if it
|
||||
rejects it, shorten it. Treat this sheet as a target, not a contract.
|
||||
- **Redaction markup counts.** Wrapping text in `~~double tildes~~` renders it
|
||||
struck-through; the four `~` characters count toward the field length even
|
||||
though they don't appear on the flyer.
|
||||
- **Re-measuring.** If the flyer layout, font, or letter-spacing policy
|
||||
changes, these numbers should be re-derived by rendering each script at print
|
||||
size and binary-searching each field for the largest run of characters that
|
||||
does not overflow the field target or the sheet.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# Utilisation détaillée
|
||||
|
||||
Ce guide couvre les flux de travail CLI courants. Consultez `docs/docker.md` pour les instructions Docker et `docs/templates.md` pour les modèles de flyers disponibles.
|
||||
|
||||
## Prérequis
|
||||
|
||||
VoxVera est conçu pour être hautement portable et nécessite un minimum de dépendances système.
|
||||
|
||||
### 1. Binaires autonomes (Recommandé)
|
||||
Vous pouvez télécharger des binaires autonomes sans dépendance pour votre système d'exploitation :
|
||||
- **Linux :** `voxvera-linux`
|
||||
- **Windows :** `voxvera-windows.exe`
|
||||
- **macOS :** `voxvera-macos`
|
||||
|
||||
Ces binaires incluent tout le nécessaire pour exécuter VoxVera (sauf `onionshare-cli`).
|
||||
|
||||
### 2. Installateur en une ligne
|
||||
Alternativement, installez via notre script automatisé :
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. Installation Python manuelle
|
||||
Si vous préférez exécuter à partir des sources :
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## Étape par étape
|
||||
|
||||
1. **Initialiser :** Exécutez `voxvera init` et suivez les instructions. Il vous sera demandé de choisir votre langue en premier.
|
||||
2. **Construire :** Générez les fichiers du flyer. Chaque construction crée automatiquement un `voxvera-portable.zip` dans le dossier du flyer, permettant aux autres de télécharger l'outil complet directement depuis votre flyer.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Servir :** Publiez le flyer sur Tor :
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
Ceci détecte automatiquement votre instance Tor, démarre OnionShare et écrit l'adresse .onion générée dans les liens détachables du flyer.
|
||||
|
||||
## Support linguistique
|
||||
|
||||
VoxVera est entièrement localisé. Vous pouvez changer votre préférence linguistique de manière permanente en utilisant soit le sélecteur interactif, soit un raccourci direct :
|
||||
|
||||
- **Sélecteur interactif :** `voxvera lang`
|
||||
- **Raccourci direct :** `voxvera --lang fr` (définit la préférence sur le français)
|
||||
|
||||
### Langues supportées :
|
||||
- **Anglais :** `en`
|
||||
- **Espagnol :** `es` (alias : `--idioma`)
|
||||
- **Allemand :** `de` (alias : `--sprache`)
|
||||
- **Français :** `fr`
|
||||
|
||||
Vous pouvez également forcer une langue spécifique pour une seule commande sans changer votre préférence permanente :
|
||||
- **Anglais :** `voxvera --lang en check`
|
||||
- **Français :** `voxvera --lang fr check`
|
||||
|
||||
Les flyers générés détectent automatiquement la langue du navigateur du visiteur et adaptent le texte de l'interface en conséquence.
|
||||
|
||||
## Gestion des serveurs
|
||||
|
||||
Gérez plusieurs flyers et leurs identités Tor à partir d'un seul menu interactif :
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Fonctionnalités :
|
||||
- **--- Créer un nouveau site/flyer ---** : Démarre la séquence de configuration complète.
|
||||
- **--- Démarrer tous les sites ---** : Lance ou arrête tous les flyers de votre flotte en une seule fois.
|
||||
- **Statut en temps réel** : Visualisez les URL .onion actives et les indicateurs de progression de l'amorçage Tor.
|
||||
- **Contrôle individuel** : Exporter en Zip des sites spécifiques vers ZIP ou supprimez-les.
|
||||
|
||||
## Mise en miroir universelle (Distribution virale)
|
||||
|
||||
Pour garantir que VoxVera reste accessible même si les dépôts centraux sont censurés, chaque flyer agit comme un miroir pour l'outil.
|
||||
|
||||
Lorsque vous hébergez un flyer, le bouton **"Télécharger l'outil et le code"** sur la page d'accueil fournit un `voxvera-portable.zip` contenant :
|
||||
- Le code source complet et toutes les langues supportées.
|
||||
- Toutes les dépendances Python (pré-vendues).
|
||||
- Les binaires Tor multiplateformes.
|
||||
|
||||
Cela permet à quiconque scanne votre flyer de devenir un nouveau distributeur de l'outil VoxVera.
|
||||
|
||||
## Exportation & Sauvegarde
|
||||
|
||||
Sauvegardez vos identités Tor uniques (pour que votre URL .onion ne change jamais) ou déplacez vos flyers vers une autre machine.
|
||||
|
||||
- **Exporter un seul site** : `voxvera export <nom_du_dossier>`
|
||||
- **Exporter tous les sites** : `voxvera export-all`
|
||||
|
||||
**Lieu de stockage :** Toutes les exportations sont sauvegardées dans `~/voxvera-exports/` sur toutes les plateformes.
|
||||
|
||||
## Importation & Récupération
|
||||
|
||||
Restaurez toute votre configuration sur une nouvelle machine en déplaçant vos fichiers ZIP vers `~/voxvera-exports/` et en exécutant :
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Portabilité & Utilisation hors ligne
|
||||
|
||||
Si vous devez exécuter VoxVera sur une machine sans accès à Internet, vous pouvez d'abord "vendeuriser" les dépendances :
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
Ceci télécharge toutes les bibliothèques Python requises dans `voxvera/vendor/`. L'outil donnera alors la priorité à ces fichiers locaux, lui permettant de s'exécuter sans `pip install`.
|
||||
|
||||
## Importation par lot (JSON)
|
||||
|
||||
Pour générer en masse des flyers à partir de plusieurs fichiers de configuration JSON, placez-les dans le répertoire `imports/` et exécutez :
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## Comment fonctionnent les URL
|
||||
|
||||
Chaque flyer possède deux URL distinctes :
|
||||
- **Lien détachable** (auto-généré) : L'adresse .onion où le flyer est hébergé.
|
||||
- **Lien de contenu** (configuré par l'utilisateur) : Une URL externe pointant vers un site web, une vidéo ou un téléchargement.
|
||||
|
||||
Vous n'avez pas besoin de saisir manuellement l'adresse .onion ; VoxVera s'en occupe automatiquement pendant la phase `serve`.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,152 +0,0 @@
|
||||
# Detailed Usage
|
||||
|
||||
This guide covers common CLI workflows. See `docs/docker.md` for Docker instructions and `docs/templates.md` for available flyer templates.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
VoxVera is designed to be highly portable. You can run it directly from the source code on any platform with Python installed.
|
||||
|
||||
Linux with `systemd --user` is the supported persistent-host environment. Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and should not yet be treated as equally reliable hidden-service deployment targets.
|
||||
|
||||
### 1. Automated Install (Recommended)
|
||||
The easiest way to install VoxVera is using the Linux-first installer script:
|
||||
|
||||
**Linux / macOS:**
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
On Linux, this also installs the recurring recovery timer used to retry hidden-service startup after boot and after missed/offline periods.
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
irm https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.ps1 | iex
|
||||
```
|
||||
The Windows installer is experimental and does not yet guarantee production-ready background hosting behavior.
|
||||
|
||||
### 2. Manual Source Install
|
||||
If you have downloaded the source code ZIP:
|
||||
|
||||
1. **Extract** the ZIP file.
|
||||
2. **Open a terminal** in the extracted folder.
|
||||
3. **Run the setup script**:
|
||||
- **Linux/macOS:** `./setup.sh`
|
||||
- **Windows:** `.\voxvera-install.sh` (or run `python -m pip install .`)
|
||||
|
||||
## Uninstallation
|
||||
|
||||
If you wish to remove VoxVera from your system, you can use the provided uninstall scripts from the source directory. This will safely remove the CLI tool and any downloaded dependencies.
|
||||
|
||||
- **Linux / macOS:** Run `./uninstall.sh`
|
||||
- **Windows (PowerShell):** Run `.\uninstall.ps1`
|
||||
|
||||
*Note: Uninstallation will not delete your generated flyers or your `.onion` keys stored in the `~/voxvera-exports` or local `host/` folders.*
|
||||
|
||||
## Step-by-Step
|
||||
|
||||
1. **Initialize:** Run `voxvera init` and follow the prompts. You will be asked to select your language first.
|
||||
2. **Build:** Generate the flyer assets. Every build automatically creates a `voxvera-portable.zip` in the flyer's folder, allowing others to download the full tool directly from your flyer.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Serve:** Publish the flyer over Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
This automatically detects your Tor instance, starts OnionShare, and writes the generated .onion address into the flyer's tear-off links.
|
||||
|
||||
### Persistent Hosting On Linux
|
||||
|
||||
For a machine that should resume hosting automatically after boot or after being offline, install the autostart recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
```
|
||||
|
||||
This installs a `systemd --user` timer that reruns `voxvera start-all` every few minutes. The retry loop is the supported way to recover hidden-service hosting after suspend, reboot, or temporary network loss.
|
||||
|
||||
## Language Support
|
||||
|
||||
VoxVera is fully localized. You can change your language preference permanently using either the interactive selector or a direct shortcut:
|
||||
|
||||
- **Interactive Selector:** `voxvera lang`
|
||||
- **Direct Shortcut:** `voxvera --lang de` (sets preference to German)
|
||||
|
||||
### Supported Languages:
|
||||
- **English:** `en`
|
||||
- **Spanish:** `es` (alias: `--idioma`)
|
||||
- **German:** `de` (alias: `--sprache`)
|
||||
|
||||
You can also force a specific language for a single command without changing your permanent preference:
|
||||
- **English:** `voxvera --lang en check`
|
||||
- **German:** `voxvera --sprache de check`
|
||||
- **Spanish:** `voxvera --idioma es check`
|
||||
|
||||
The generated flyers automatically detect the visitor's browser language and switch the UI text accordingly.
|
||||
|
||||
## Server Management
|
||||
|
||||
Manage multiple flyers and their Tor identities from a single interactive menu:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Features:
|
||||
- **--- צור אתר/פלייר חדש ---**: Start the full setup sequence.
|
||||
- **--- הפעל את כל האתרים ---**: Launch or shut down every flyer in your fleet at once.
|
||||
- **Real-time Status**: View active `.onion` URLs and Tor bootstrapping progress indicators.
|
||||
- **Individual Control**: ייצא ל-Zip specific sites to ZIP or delete them.
|
||||
|
||||
## Universal Mirroring (Viral Distribution)
|
||||
|
||||
To ensure VoxVera remains accessible even if central repositories are censored, every flyer acts as a mirror for the tool.
|
||||
|
||||
When you host a flyer, the **"הורד כלי וקוד מקור"** button on the landing page provides a `voxvera-source.zip` containing:
|
||||
- The full source code and all supported languages.
|
||||
- Installation and setup scripts for all platforms.
|
||||
- Complete documentation and templates.
|
||||
|
||||
This allows anyone who scans your flyer to become a new distributor of the VoxVera tool.
|
||||
|
||||
## Export & Backup
|
||||
|
||||
Back up your unique Tor identities (so your `.onion` URL never changes) or move your flyers to another machine.
|
||||
|
||||
- **Export a single site**: `voxvera export <folder_name>`
|
||||
- **Export all sites**: `voxvera export-all`
|
||||
|
||||
**Storage location:** All exports are saved to `~/voxvera-exports/` on all platforms.
|
||||
|
||||
## Import & Recovery
|
||||
|
||||
Restore your entire setup on a new machine by moving your ZIP files to `~/voxvera-exports/` and running:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Portability & Offline Use
|
||||
|
||||
If you need to run VoxVera on a machine without internet access, you can "vendorize" the dependencies first:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
This downloads all required Python libraries into `voxvera/vendor/`. The tool will then prioritize these local files, allowing it to run without `pip install`.
|
||||
|
||||
## Batch Import (JSON)
|
||||
|
||||
To bulk-generate flyers from multiple JSON configuration files, place them in the `imports/` directory and run:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## How URLs Work
|
||||
|
||||
Each flyer has two separate URLs:
|
||||
- **Tear-off link** (auto-generated): The .onion address where the flyer is hosted.
|
||||
- **Content link** (user-configured): An external URL pointing to a website, video, or download.
|
||||
|
||||
You do not need to manually enter the .onion address; VoxVera handles this automatically during the `serve` phase.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# विस्तृत उपयोग
|
||||
|
||||
यह गाइड सामान्य CLI वर्कफ्लो को कवर करती है। डॉकर निर्देशों के लिए `docs/docker.md` और उपलब्ध फ्लायर टेम्पलेट्स के लिए `docs/templates.md` देखें।
|
||||
|
||||
## पूर्वापेक्षाएँ (Prerequisites)
|
||||
|
||||
VoxVera को अत्यधिक पोर्टेबल बनाने के लिए डिज़ाइन किया गया है और इसके लिए न्यूनतम सिस्टम निर्भरता की आवश्यकता होती है।
|
||||
|
||||
### 1. स्टैंडअलोन बाइनरी (अनुशंसित)
|
||||
आप अपने ऑपरेटिंग सिस्टम के लिए स्टैंडअलोन, शून्य-निर्भरता बाइनरी डाउनलोड कर सकते हैं:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
इन बाइनरी में VoxVera चलाने के लिए आवश्यक सब कुछ शामिल है (`onionshare-cli` को छोड़कर)।
|
||||
|
||||
### 2. वन-लाइन इंस्टॉलर
|
||||
वैकल्पिक रूप से, हमारी स्वचालित स्क्रिप्ट के माध्यम से इंस्टॉल करें:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. मैनुअल पायथन इंस्टॉलेशन
|
||||
यदि आप सोर्स से चलाना पसंद करते हैं:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## चरण-दर-चरण (Step-by-Step)
|
||||
|
||||
1. **आरंभ करें (Initialize):** `voxvera init` चलाएँ और संकेतों का पालन करें। आपसे सबसे पहले अपनी भाषा चुनने के लिए कहा जाएगा।
|
||||
2. **बिल्ड (Build):** फ्लायर एसेट्स जेनरेट करें। प्रत्येक बिल्ड स्वचालित रूप से फ्लायर के फ़ोल्डर में एक `voxvera-portable.zip` बनाता है, जिससे अन्य लोग सीधे आपके फ्लायर से पूरा टूल डाउनलोड कर सकते हैं।
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **सर्व (Serve):** फ्लायर को Tor पर प्रकाशित करें:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
यह स्वचालित रूप से आपके Tor इंस्टेंस का पता लगाता है, OnionShare शुरू करता है, और जेनरेट किए गए .onion एड्रेस को फ्लायर के टियर-ऑफ लिंक में लिख देता है।
|
||||
|
||||
## भाषा समर्थन (Language Support)
|
||||
|
||||
VoxVera पूरी तरह से स्थानीयकृत (localized) है। आप इंटरैक्टिव सेलेक्टर या सीधे शॉर्टकट का उपयोग करके अपनी भाषा प्राथमिकता को स्थायी रूप से बदल सकते हैं:
|
||||
|
||||
- **इंटरैक्टिव सेलेक्टर:** `voxvera lang`
|
||||
- **सीधा शॉर्टकट:** `voxvera --lang hi` (प्राथमिकता को हिन्दी पर सेट करता है)
|
||||
|
||||
### समर्थित भाषाएं:
|
||||
- **अंग्रेजी:** `en`
|
||||
- **स्पेनिश:** `es` (उपनाम: `--idioma`)
|
||||
- **जर्मन:** `de` (उपनाम: `--sprache`)
|
||||
- **हिन्दी:** `hi`
|
||||
|
||||
आप अपनी स्थायी प्राथमिकता को बदले बिना किसी एक कमांड के लिए एक विशिष्ट भाषा को बाध्य (force) भी कर सकते हैं:
|
||||
- **अंग्रेजी:** `voxvera --lang en check`
|
||||
- **हिन्दी:** `voxvera --lang hi check`
|
||||
|
||||
जेनरेट किए गए फ्लायर्स स्वचालित रूप से विज़िटर की ब्राउज़र भाषा का पता लगाते हैं और उसके अनुसार UI टेक्स्ट बदलते हैं।
|
||||
|
||||
## सर्वर प्रबंधन (Server Management)
|
||||
|
||||
एक ही इंटरैक्टिव मेनू से कई फ्लायर्स और उनकी Tor पहचान प्रबंधित करें:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
विशेषताएं:
|
||||
- **--- नई साइट/फ्लायर बनाएँ ---**: पूरा सेटअप अनुक्रम शुरू करें।
|
||||
- **--- सभी साइटें शुरू करें ---**: अपने बेड़े के सभी फ्लायर्स को एक साथ शुरू या बंद करें।
|
||||
- **वास्तविक समय स्थिति**: सक्रिय `.onion` URL और Tor बूटस्ट्रैपिंग प्रगति संकेतक देखें।
|
||||
- **व्यक्तिगत नियंत्रण**: विशिष्ट साइटों को ZIP में ज़िप में निर्यात करें करें या उन्हें हटा दें।
|
||||
|
||||
## यूनिवर्सल मिररिंग (वायरल वितरण)
|
||||
|
||||
यह सुनिश्चित करने के लिए कि VoxVera केंद्रीय रिपॉजिटरी सेंसर होने पर भी सुलभ रहे, प्रत्येक फ्लायर टूल के लिए मिरर के रूप में कार्य करता है।
|
||||
|
||||
जब आप फ्लायर होस्ट करते हैं, तो लैंडिंग पेज पर **"टूल और कोड डाउनलोड करें"** बटन एक `voxvera-portable.zip` प्रदान करता है जिसमें शामिल हैं:
|
||||
- पूरा सोर्स कोड और सभी समर्थित भाषाएं।
|
||||
- सभी पायथन निर्भरताएँ (pre-vendored)।
|
||||
- क्रॉस-प्लेटफ़ॉर्म Tor बाइनरी।
|
||||
|
||||
यह आपके फ्लायर को स्कैन करने वाले किसी भी व्यक्ति को VoxVera टूल का नया वितरक बनने की अनुमति देता है।
|
||||
|
||||
## निर्यात और बैकअप (Export & Backup)
|
||||
|
||||
अपनी अनूठी Tor पहचान का बैकअप लें (ताकि आपका `.onion` URL कभी न बदले) या अपने फ्लायर्स को दूसरी मशीन पर ले जाएं।
|
||||
|
||||
- **एकल साइट निर्यात करें**: `voxvera export <folder_name>`
|
||||
- **सभी साइटें निर्यात करें**: `voxvera export-all`
|
||||
|
||||
**भंडारण स्थान:** सभी निर्यात सभी प्लेटफ़ॉर्म पर उपयोगकर्ता की होम डायरेक्टरी (`~/voxvera-exports/`) में ZIP फ़ाइलों के रूप में सहेजे जाते हैं।
|
||||
|
||||
## आयात और पुनर्प्राप्ति (Import & Recovery)
|
||||
|
||||
अपनी ZIP फ़ाइलों को `~/voxvera-exports/` में ले जाकर और चलाकर एक नई मशीन पर अपना पूरा सेटअप पुनर्स्थापित करें:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## पोर्टेबिलिटी और ऑफलाइन उपयोग
|
||||
|
||||
यदि आपको बिना इंटरनेट एक्सेस वाली मशीन पर VoxVera चलाने की आवश्यकता है, तो आप पहले निर्भरताओं को "वेंडराइज़" (vendorize) कर सकते हैं:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
यह `voxvera/vendor/` में सभी आवश्यक पायथन लाइब्रेरी डाउनलोड करता है। टूल फिर इन स्थानीय फ़ाइलों को प्राथमिकता देगा, जिससे यह `pip install` के बिना चल सकेगा।
|
||||
|
||||
## बैच आयात (JSON)
|
||||
|
||||
कई JSON कॉन्फ़िगरेशन फ़ाइलों से थोक में फ्लायर्स जेनरेट करने के लिए, उन्हें `imports/` डायरेक्टरी में रखें और चलाएँ:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## URL कैसे काम करते हैं
|
||||
|
||||
प्रत्येक फ्लायर के दो अलग-अलग URL होते हैं:
|
||||
- **टियर-ऑफ लिंक** (स्वचालित रूप से जेनरेट): वह .onion एड्रेस जहाँ फ्लायर होस्ट किया गया है।
|
||||
- **सामग्री लिंक** (उपयोगकर्ता-कॉन्फ़िगर): वेबसाइट, वीडियो या डाउनलोड की ओर इशारा करने वाला एक बाहरी URL।
|
||||
|
||||
आपको मैन्युअल रूप से .onion एड्रेस दर्ज करने की आवश्यकता नहीं है; `serve` चरण के दौरान VoxVera इसे स्वचालित रूप से संभालता है।
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# 詳細な使い方
|
||||
|
||||
このガイドでは、一般的なCLIワークフローについて説明します。Dockerの手順については `docs/docker.md` を、利用可能なフライヤーテンプレートについては `docs/templates.md` を参照してください。
|
||||
|
||||
## 前提条件
|
||||
|
||||
VoxVeraは高いポータビリティを実現するように設計されており、システムへの依存関係は最小限です。
|
||||
|
||||
### 1. スタンドアロンバイナリ (推奨)
|
||||
お使いのオペレーティングシステムに合わせて、依存関係のないスタンドアロンバイナリをダウンロードできます。
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
これらのバイナリには、VoxVeraの実行に必要なすべてのものが含まれています(`onionshare-cli` を除く)。
|
||||
|
||||
### 2. ワンラインインストーラー
|
||||
または、自動スクリプトを使用してインストールします。
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. 手動でのPythonインストール
|
||||
ソースから実行したい場合:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## ステップ・バイ・ステップ
|
||||
|
||||
1. **初期化:** `voxvera init` を実行し、プロンプトに従います。最初に言語を選択するよう求められます。
|
||||
2. **ビルド:** フライヤーのアセットを生成します。ビルドを実行するたびに、フライヤーのフォルダ内に `voxvera-portable.zip` が自動的に作成されます。これにより、他の人があなたのフライヤーから直接ツール一式をダウンロードできるようになります。
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **公開:** Torを介してフライヤーを公開します。
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
これにより、実行中のTorインスタンスが自動的に検出され、OnionShareが起動し、生成された .onion アドレスがフライヤーの切り取りセクションのリンクに書き込まれます。
|
||||
|
||||
## 言語サポート
|
||||
|
||||
VoxVeraは完全にローカライズされています。インタラクティブセレクターまたは直接ショートカットを使用して、言語設定を永続的に変更できます。
|
||||
|
||||
- **インタラクティブセレクター:** `voxvera lang`
|
||||
- **直接ショートカット:** `voxvera --lang ja` (日本語に設定)
|
||||
|
||||
### サポートされている言語:
|
||||
- **英語:** `en`
|
||||
- **スペイン語:** `es` (エイリアス: `--idioma`)
|
||||
- **ドイツ語:** `de` (エイリアス: `--sprache`)
|
||||
- **日本語:** `ja`
|
||||
|
||||
永続的な設定を変更せずに、単一のコマンドに対して特定の言語を強制することもできます。
|
||||
- **英語:** `voxvera --lang en check`
|
||||
- **日本語:** `voxvera --lang ja check`
|
||||
|
||||
生成されたフライヤーは、訪問者のブラウザ言語を自動的に検出し、UIテキストをそれに応じて切り替えます。
|
||||
|
||||
## サーバー管理
|
||||
|
||||
単一のインタラクティブメニューから、複数のフライヤーとそのTorアイデンティティを管理できます。
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
機能:
|
||||
- **--- 新規サイト/フライヤー作成 ---**: セットアップシーケンスを最初から開始します。
|
||||
- **--- すべてのサイトを開始 ---**: 管理下のすべてのフライヤーを一括で起動またはシャットダウンします。
|
||||
- **リアルタイムステータス**: アクティブな .onion URLやTorの起動プログレスインジケーターを表示します。
|
||||
- **個別制御**: 特定のサイトをZIPに Zipとしてエクスポート したり、削除したりできます。
|
||||
|
||||
## ユニバーサルミラーリング(バイラル拡散)
|
||||
|
||||
中央のリポジトリが検閲された場合でもVoxVeraを利用し続けられるように、すべてのフライヤーがツールのミラーとして機能します。
|
||||
|
||||
フライヤーをホストすると、ランディングページの **「ツールとソースをダウンロード」** ボタンから以下のものを含む `voxvera-portable.zip` が提供されます。
|
||||
- すべてのサポート言語を含む完全なソースコード。
|
||||
- すべてのPython依存関係(事前ベンダー化済み)。
|
||||
- クロスプラットフォームのTorバイナリ。
|
||||
|
||||
これにより、あなたのフライヤーをスキャンした誰もが、VoxVeraツールの新しい配布者になることができます。
|
||||
|
||||
## エクスポートとバックアップ
|
||||
|
||||
独自のTorアイデンティティ(.onion URLが変更されないようにするため)をバックアップしたり、フライヤーを別のマシンに移動したりできます。
|
||||
|
||||
- **単一サイトのエクスポート**: `voxvera export <フォルダ名>`
|
||||
- **全サイトのエクスポート**: `voxvera export-all`
|
||||
|
||||
**保存場所:** すべてのエクスポートは、すべてのプラットフォームでユーザーのホームディレクトリにある `~/voxvera-exports/` フォルダに保存されます。
|
||||
|
||||
## インポートと復元
|
||||
|
||||
ZIPファイルを `~/voxvera-exports/` に移動して以下を実行することで、新しいマシンでセットアップ全体を復元できます。
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## ポータビリティとオフライン利用
|
||||
|
||||
インターネット接続のないマシンでVoxVeraを実行する必要がある場合は、まず依存関係を「ベンダー化」できます。
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
これにより、必要なすべてのPythonライブラリが `voxvera/vendor/` にダウンロードされます。ツールはこれらのローカルファイルを優先的に使用するため、 `pip install` なしで実行できるようになります。
|
||||
|
||||
## 一括インポート (JSON)
|
||||
|
||||
複数のJSON設定ファイルからフライヤーを一括生成するには、それらを `imports/` ディレクトリに配置して以下を実行します。
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## URLの仕組み
|
||||
|
||||
各フライヤーには2つの異なるURLがあります。
|
||||
- **切り取り用リンク** (自動生成): フライヤーがホストされている .onion アドレス。
|
||||
- **コンテンツリンク** (ユーザー設定): ウェブサイト、動画、またはダウンロードを指す外部URL。
|
||||
|
||||
.onion アドレスを手動で入力する必要はありません。VoxVeraが `serve` フェーズ中に自動的に処理します。
|
||||
@@ -1,178 +0,0 @@
|
||||
# Linux Hosting Validation
|
||||
|
||||
This runbook defines the operational validation standard for VoxVera's only supported hosting target:
|
||||
|
||||
- Linux CLI with `systemd --user`
|
||||
|
||||
Everything else remains below that bar until equivalent evidence exists.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `voxvera` installed and on `PATH`
|
||||
- `tor` installed
|
||||
- `onionshare-cli` available
|
||||
- a user account that can run `systemctl --user`
|
||||
|
||||
## Quick Verification
|
||||
|
||||
Use the helper script first:
|
||||
|
||||
```bash
|
||||
bash scripts/linux-recovery-check.sh
|
||||
```
|
||||
|
||||
This checks:
|
||||
|
||||
- `platform-status --json`
|
||||
- `doctor --json`
|
||||
- `autostart status --json`
|
||||
- expected Linux support tier and platform id
|
||||
- presence of `~/host`
|
||||
- Tor and OnionShare discovery
|
||||
- autostart artifacts and timer state
|
||||
- per-site state for `.onionshare-session`, `onionshare.log`, and `server.pid`
|
||||
|
||||
## Core Commands
|
||||
|
||||
Install autostart:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
```
|
||||
|
||||
Inspect autostart:
|
||||
|
||||
```bash
|
||||
voxvera autostart status
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
Remove autostart:
|
||||
|
||||
```bash
|
||||
voxvera autostart uninstall
|
||||
```
|
||||
|
||||
Inspect runtime diagnostics:
|
||||
|
||||
```bash
|
||||
voxvera doctor
|
||||
voxvera doctor --json
|
||||
```
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
### 1. Fresh install
|
||||
|
||||
Run the Linux installer or install through the supported CLI path, then confirm:
|
||||
|
||||
```bash
|
||||
voxvera platform-status --json
|
||||
voxvera doctor --json
|
||||
voxvera autostart status --json
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `platform_id` is `linux_cli_systemd`
|
||||
- support tier is `supported`
|
||||
- `voxvera_cli`, `onionshare_cli`, and `tor_binary` pass
|
||||
|
||||
### 2. Build and serve
|
||||
|
||||
Create or edit a site, then build and serve it:
|
||||
|
||||
```bash
|
||||
voxvera build
|
||||
voxvera serve
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- site output appears under `~/host/<folder_name>/`
|
||||
- `index.html` and QR code images exist
|
||||
- `onionshare.log` is written
|
||||
- `.onionshare-session` appears after the hidden service is started
|
||||
|
||||
### 3. Identity persistence
|
||||
|
||||
Confirm the site keeps its identity across rebuilds:
|
||||
|
||||
```bash
|
||||
ls -la ~/host/<folder_name>/
|
||||
voxvera build --config ~/host/<folder_name>/config.json
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `.onionshare-session` still exists after rebuild
|
||||
|
||||
### 4. Autostart persistence
|
||||
|
||||
Confirm the recovery timer exists and is enabled:
|
||||
|
||||
```bash
|
||||
voxvera autostart status
|
||||
systemctl --user is-enabled voxvera-start.timer
|
||||
systemctl --user is-active voxvera-start.timer
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- timer artifacts exist under `~/.config/systemd/user/`
|
||||
- timer is enabled
|
||||
|
||||
### 5. Reboot recovery
|
||||
|
||||
After a reboot, verify:
|
||||
|
||||
```bash
|
||||
bash scripts/linux-recovery-check.sh
|
||||
systemctl --user status voxvera-start.timer
|
||||
journalctl --user -u voxvera-start.service --no-pager -n 50
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- timer remains enabled
|
||||
- service has retried `start-all`
|
||||
- configured sites are restorable without manual reconfiguration
|
||||
|
||||
### 6. Offline/reconnect recovery
|
||||
|
||||
Temporarily disconnect the host from the network, reconnect, then wait through at least one timer interval.
|
||||
|
||||
Verify:
|
||||
|
||||
```bash
|
||||
systemctl --user status voxvera-start.timer
|
||||
journalctl --user -u voxvera-start.service --no-pager -n 50
|
||||
bash scripts/linux-recovery-check.sh
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- timer is still active
|
||||
- `start-all` retries appear in the service logs
|
||||
- Tor becomes reachable again
|
||||
|
||||
## Paths That Matter
|
||||
|
||||
- `~/.config/systemd/user/voxvera-start.service`
|
||||
- `~/.config/systemd/user/voxvera-start.timer`
|
||||
- `~/host/<folder_name>/config.json`
|
||||
- `~/host/<folder_name>/.onionshare-session`
|
||||
- `~/host/<folder_name>/onionshare.log`
|
||||
- `~/host/<folder_name>/server.pid`
|
||||
|
||||
## Failure Interpretation
|
||||
|
||||
If `bash scripts/linux-recovery-check.sh` fails:
|
||||
|
||||
- missing `onionshare_cli` or `tor_binary` means the runtime is incomplete
|
||||
- missing `host_root` means no sites are built yet
|
||||
- missing autostart artifacts means recovery was never installed or was removed
|
||||
- `tor_socks_reachable` warning means Tor is not currently reachable even if it is installed
|
||||
|
||||
Linux should remain the only supported target until this runbook is repeatable on real hosts without caveats.
|
||||
@@ -1,99 +0,0 @@
|
||||
# Multi-Language Support Developer Plan
|
||||
|
||||
This document outlines the strategy for implementing a token-based multi-language system in VoxVera, covering the CLI, the generated landing page, and documentation.
|
||||
|
||||
## 1. Core Architecture: The Token System
|
||||
|
||||
All translatable strings will be centralized in JSON files located in `voxvera/locales/`. This allows for easy addition of new languages by simply dropping a new file.
|
||||
|
||||
- **Storage:** `voxvera/locales/{lang_code}.json` (e.g., `en.json`, `es.json`).
|
||||
- **Structure:**
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"language_name": "English",
|
||||
"flag": "🇺🇸"
|
||||
},
|
||||
"cli": {
|
||||
"welcome": "Welcome to VoxVera Setup",
|
||||
"select_lang": "Select your preferred language",
|
||||
"folder_prompt": "Enter folder name for this flyer:"
|
||||
},
|
||||
"web": {
|
||||
"title": "VoxVera - Anonymous Flyers",
|
||||
"download_btn": "Download Flyer",
|
||||
"onion_link_desc": "Scan to view on Tor",
|
||||
"change_lang": "Change Language"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. CLI Implementation (`voxvera/cli.py`)
|
||||
|
||||
The CLI will be updated to handle localization from the start of the user interaction.
|
||||
|
||||
### Workflow:
|
||||
1. **Initial Detection:** On startup, the CLI checks the system locale (`LANG` env var or `locale` module).
|
||||
2. **Language Selection:** The first prompt in `voxvera init` will be a language selector, defaulting to the detected system locale.
|
||||
3. **Session Loading:** Once selected, the CLI loads the corresponding JSON. All subsequent `InquirerPy` prompts will use these tokens.
|
||||
4. **Configuration:** The chosen language code is saved in the flyer's `config.json` as a preference for that specific project.
|
||||
|
||||
## 3. Web Implementation (`voxvera/src/index-master.html`)
|
||||
|
||||
The landing page will support dynamic language switching without requiring server-side logic (essential for Tor-hidden services).
|
||||
|
||||
### Detection Logic:
|
||||
- **Avoid IP-based Detection:** Since VoxVera is hosted on Tor, IP lookups return the Tor Exit Node location, not the user's.
|
||||
- **Browser-based Detection:** Use `navigator.language` to detect the user's browser preference.
|
||||
- **Persistence:** Save the user's manual choice in `localStorage`.
|
||||
|
||||
### Frontend Components:
|
||||
1. **Attributes:** Use `data-i18n="web.token_name"` on HTML elements.
|
||||
2. **Language Switcher:** A dropdown menu or text-link list (e.g., "EN | ES | FR") placed next to the **Download** button.
|
||||
3. **I18n Engine:** A lightweight JavaScript snippet injected during the build process that:
|
||||
- Loads the bundled locale data.
|
||||
- Detects the best language (Manual Selection > Browser Setting > English Fallback).
|
||||
- Updates all `data-i18n` elements.
|
||||
|
||||
## 4. Build System Updates (`voxvera/build.py`)
|
||||
|
||||
The `build` process will be updated to bundle the necessary translations.
|
||||
|
||||
- **Multi-bundle:** By default, all available `web` tokens from all locale files will be injected into a single `<script>` tag in the final `index.html`. This ensures instant switching even when offline or on slow Tor connections.
|
||||
- **Asset Optimization:** Minify the locale JSON data before injection to keep the HTML lightweight.
|
||||
|
||||
## 5. Portable & Viral Distribution Model
|
||||
|
||||
To ensure VoxVera is truly censorship-resistant, every generated flyer will serve as a mirror for the entire tool, including all supported languages and dependencies.
|
||||
|
||||
### Key Requirements:
|
||||
- **Zero-Dependency Execution:** All Python libraries (from `requirements.txt`) will be bundled into a `voxvera/vendor/` directory. The CLI will be updated to prioritize this local path.
|
||||
- **Pre-Bundled Tor:** The existing `voxvera/resources/tor/` binaries for Linux, Mac, and Windows will be included in every distribution.
|
||||
- **Universal Language Bundle:** Every `voxvera-portable.zip` will include the full `voxvera/locales/` directory, ensuring that a user who downloads the tool from an English flyer can immediately switch it to Spanish, French, or any other supported language.
|
||||
|
||||
### The "Mirror" Workflow:
|
||||
1. **Build Phase:** When `voxvera build` is executed, it assembles a `voxvera-portable.zip` containing:
|
||||
- The full `voxvera/` source code.
|
||||
- The `vendor/` library directory.
|
||||
- All `locales/*.json` files.
|
||||
- Cross-platform Tor binaries.
|
||||
- A `voxvera-run.sh` / `voxvera-run.bat` entry point.
|
||||
2. **Injection:** This ZIP is automatically placed in the `voxvera/host/<folder_name>/download/` directory of the generated flyer.
|
||||
3. **User Access:** The landing page's "Download" button is updated to explicitly offer the "Full Portable Tool & Source," allowing the recipient to become a new node in the distribution network.
|
||||
|
||||
## 6. Documentation (`docs/`)
|
||||
|
||||
Documentation will follow a subdirectory structure for maximum compatibility with GitHub/Markdown renderers.
|
||||
|
||||
- **Structure:**
|
||||
- `docs/en/usage.md`
|
||||
- `docs/es/usage.md`
|
||||
- **Maintenance:** A master English file will serve as the source of truth for all translations.
|
||||
|
||||
## 6. Implementation Phases
|
||||
|
||||
1. **Phase 1 (Audit):** Extract all hardcoded strings from `cli.py` and `index-master.html` into `en.json`.
|
||||
2. **Phase 2 (CLI):** Implement the language selector and token loader in `cli.py`.
|
||||
3. **Phase 3 (Web):** Update the HTML template with `data-i18n` attributes and the JS switcher.
|
||||
4. **Phase 4 (Build):** Update `build.py` to inject the locale bundle.
|
||||
5. **Phase 5 (Expansion):** Add a second language (e.g., Spanish) to verify the system.
|
||||
@@ -0,0 +1,401 @@
|
||||
# VoxVera Nostr Static Client Spec
|
||||
|
||||
Status: `main` is the Nostr static-client branch. The legacy Tor/OnionShare CLI version is preserved on `legacy-tor`.
|
||||
|
||||
## Goal
|
||||
|
||||
VoxVera should let anyone publish, fetch, and print flyer content without a centralized application server.
|
||||
|
||||
The static client is responsible for:
|
||||
|
||||
- rendering the flyer
|
||||
- generating QR codes
|
||||
- authoring a normalized Nostr flyer payload
|
||||
- generating anonymous browser-side Nostr keys
|
||||
- signing and publishing replaceable Nostr events
|
||||
- fetching events by raw event ID, `note1`, `nevent1`, or `naddr`
|
||||
- rendering fetched content safely
|
||||
|
||||
Nostr relays store the flyer source content. Static hosts only serve the client.
|
||||
|
||||
## Active Files
|
||||
|
||||
```text
|
||||
site/
|
||||
index.html (the client)
|
||||
nostr-client.css
|
||||
nostr-client.js
|
||||
locales.js
|
||||
board.html (bulletin board page)
|
||||
board.js
|
||||
favicon.svg (inline SVG site icon)
|
||||
CNAME
|
||||
vendor/
|
||||
nostr-tools/
|
||||
qrcode-generator/
|
||||
nostr/
|
||||
index.html (redirect stub for legacy /nostr/ URLs)
|
||||
voxvera/
|
||||
nostr/
|
||||
schema.py
|
||||
tests/
|
||||
test_nostr_schema.py
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
The deployable static root is `site`.
|
||||
|
||||
No build command is required. Vercel should use:
|
||||
|
||||
- root directory: repository root
|
||||
- output directory: `site`
|
||||
- build command: empty
|
||||
|
||||
The client is served from the root (`site/index.html`). `site/nostr/index.html` is a redirect stub that forwards the legacy `/nostr/` path to the root, preserving the query string and `#naddr` fragment, so poster URLs and QR codes printed before the move still resolve.
|
||||
|
||||
## Event Model
|
||||
|
||||
Recommended event kind: `30078` parameterized replaceable event.
|
||||
|
||||
Required tags:
|
||||
|
||||
- `["d", "voxvera:<slug>"]`
|
||||
- `["t", "voxvera"]`
|
||||
- `["t", "flyer"]`
|
||||
|
||||
Recommended language tags:
|
||||
|
||||
- `["language", "<lang>"]`
|
||||
- `["L", "ISO-639-1"]`
|
||||
- `["l", "<lang>", "ISO-639-1"]`
|
||||
|
||||
The payload `lang` field is authoritative. The language tags exist for relay/search metadata and as a fallback for older events whose payload omitted `lang`.
|
||||
|
||||
Payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "voxvera_flyer",
|
||||
"version": 1,
|
||||
"folder_name": "voxvera",
|
||||
"name": "Vox Vera Printable Flyers",
|
||||
"lang": "en",
|
||||
"title": "OPERATION VOX VERA",
|
||||
"subtitle": "DO ~~NOT~~ DISTRIBUTE",
|
||||
"headline": "TOP SECRET",
|
||||
"content": "Flyer body text",
|
||||
"url_message": "Follow this link to learn more.",
|
||||
"url": "https://creator.example/action",
|
||||
"tear_off_link": "https://voxvera.org/nostr/#naddr1...",
|
||||
"footer_message": "0110010",
|
||||
"qr_target": "flyer_url"
|
||||
}
|
||||
```
|
||||
|
||||
The UI labels `folder_name` as `Flyer Name`; it acts as the event slug, not a local hosting folder.
|
||||
|
||||
## QR Target
|
||||
|
||||
Default behavior: `qr_target: "flyer_url"`.
|
||||
|
||||
`url` is always the creator-controlled content destination shown in the body of the flyer. The editor must not overwrite this field with generated app URLs.
|
||||
|
||||
When publishing, the client computes the replaceable-event `naddr` and writes the generated poster URL to `tear_off_link`. The tear-off tabs and tear-off QR code point at `tear_off_link`, so people can re-open and reprint the flyer. The main flyer QR code points at `url`, so viewers can visit the creator's intended destination.
|
||||
|
||||
Each tear-off tab is labeled with the flyer's **title** (`.tear-off-title`, auto-sized by `fitTabTitles()` to be as large as fits the ~1in tab, shrinking rather than overflowing for long titles), a clickable **"Open & reprint this flyer"** link (`tab_link`, the `<a href>` so it stays live in a printed PDF), the tear-off QR, and a **"Reopen at VoxVera.org — Event ID:"** line (`tab_event_id`, the brand stays Latin; the rest is localized) with the full event id. All strings are translated in every supported language.
|
||||
|
||||
The `naddr` is encoded with a **single relay hint** (the primary configured relay) instead of the full relay list. This keeps the poster URL short and its tear-off QR code easy to scan — a typical poster URL drops from ~233 characters (full list) to ~171 — while still pointing a fresh viewer at a relay that has the event. Viewers also fall back to `DEFAULT_RELAYS`, which is where flyers are published by default. This stays a standard NIP-19 `naddr`, so any Nostr client can resolve it, and older relay-bearing `naddr` URLs continue to decode and resolve unchanged.
|
||||
|
||||
The naddr is carried in the URL **fragment** (`#naddr1...`) rather than a `?addr=` query parameter. The fragment is shorter (less QR clutter), needs no URL-encoding, and never reaches the static host. `getUrlEventReference` reads the naddr from query params, the fragment, or anywhere in the full URL, so older `?addr=` poster URLs and printed QR codes still resolve.
|
||||
|
||||
Supported values:
|
||||
|
||||
- `flyer_url`: tear-off QR points to the hosted client URL for the poster
|
||||
- `content_url`: QR points to the payload's content URL
|
||||
- `nostr_event`: QR points to the Nostr source identifier when available
|
||||
|
||||
## Safety
|
||||
|
||||
Nostr content is untrusted.
|
||||
|
||||
The client and schema helper must:
|
||||
|
||||
- reject raw HTML in flyer text fields
|
||||
- escape rendered flyer content
|
||||
- reject unsafe URL schemes such as `javascript:` and `data:`
|
||||
- keep attachments unsupported in V1
|
||||
- avoid remote frontend dependencies
|
||||
|
||||
## Publishing identity
|
||||
|
||||
The editor signs flyer events under one of four identities, chosen in the
|
||||
identity controls (`activeIdentity` / `signActiveEvent` in `nostr-client.js`):
|
||||
|
||||
- **Anonymous (default).** The per-device key in `localStorage`
|
||||
(`voxvera_nostr_anon_secret_hex`); signs locally with `finalizeEvent`.
|
||||
Unchanged behavior — no connection required. "Generate anonymous npub" rolls a
|
||||
fresh device key.
|
||||
- **Browser extension (NIP-07).** Signs via `window.nostr.signEvent`; the secret
|
||||
never enters the page. The pubkey is fetched with `getPublicKey()`.
|
||||
- **Private key (nsec).** The user pastes an `nsec`; it is decoded to a secret
|
||||
key used to sign with `finalizeEvent`. By default the secret lives **only in
|
||||
memory** for the session. If the user ticks "Remember on this device", the
|
||||
secret is encrypted with a PIN and stored as `voxvera_identity_nsec_enc`; the
|
||||
plaintext secret is never written to storage.
|
||||
- **Remote signer (NIP-46).** The user's real secret never reaches the browser;
|
||||
the client mints an **ephemeral** local key and exchanges encrypted
|
||||
kind-`24133` JSON-RPC requests (`connect` → `get_public_key` → `sign_event`)
|
||||
over a raw WebSocket. Two connect paths are offered:
|
||||
- **`bunker://` (paste).** The user pastes a link the signer app generated;
|
||||
the client connects out to that bunker relay.
|
||||
- **`nostrconnect://` (QR).** The client generates the link itself, renders it
|
||||
as a QR (`makeQrSvg`) plus a copyable link, and listens on a rendezvous relay
|
||||
(`relay.nsec.app`); the signer app scans it and connects back, proving the
|
||||
connection by echoing the client's random `secret`. The discovered signer
|
||||
pubkey is then used for the durable connection.
|
||||
|
||||
Requests are encrypted with **NIP-44** (with a NIP-04 decrypt fallback for
|
||||
older signers); the vendored nostr-tools bundle has no nip46 module, so this
|
||||
client is hand-rolled. The connection is **session-only** — nothing is
|
||||
persisted, so a reload returns to anonymous.
|
||||
|
||||
The chosen mode is remembered in `voxvera_identity_mode` (and the npub in
|
||||
`voxvera_identity_npub` for display). On reload: NIP-07 re-fetches the pubkey;
|
||||
a remembered nsec shows a **locked** state until the PIN is entered (`unlock`);
|
||||
a session-only nsec or a remote-signer session falls back to anonymous.
|
||||
`naddr`/poster-URL/`author npub` outputs all reflect the active identity. A
|
||||
deliberate identity choice is also mirrored to `voxvera_connected_pubkey` so the
|
||||
bulletin board reflects the same identity.
|
||||
|
||||
**PIN encryption details.** PBKDF2 (`SHA-256`, 600k iterations, random 16-byte
|
||||
salt) derives an AES-GCM-256 key (random 12-byte IV); the blob stores
|
||||
`{v, iters, salt, iv, ct}` base64. A minimum 4-digit numeric PIN is enforced,
|
||||
but longer PINs are allowed and encouraged.
|
||||
|
||||
> **Security caveat (documented deliberately).** A short numeric PIN has a tiny
|
||||
> keyspace (a 4-digit PIN is ~10,000 combinations), so if the encrypted blob is
|
||||
> exfiltrated (targeted XSS, or devtools access on a shared/stolen device) it is
|
||||
> brute-forceable offline regardless of PBKDF2 cost. PIN-at-rest protects against
|
||||
> casual snooping and untargeted localStorage scraping, **not** a determined or
|
||||
> targeted attacker. The NIP-07 extension path (secret never in the page) and the
|
||||
> NIP-46 remote signer (secret stays in the signer app; the browser holds only an
|
||||
> ephemeral key — paste a `bunker://` link) are the stronger options. See
|
||||
> [`roadmap.md`](roadmap.md).
|
||||
|
||||
## Editing, re-publishing, and deleting flyers
|
||||
|
||||
Because flyers are addressable replaceable events (`kind 30078`, identified by
|
||||
`(pubkey, d)` where `d = voxvera:<slug>`), the author can manage a published
|
||||
flyer by re-publishing under the same key + Flyer Name. When a flyer is loaded
|
||||
from an event, the editor shows author-only actions (`#loaded-flyer-actions`):
|
||||
|
||||
- **Edit** — change fields and publish again; the same `d` tag replaces the
|
||||
prior version in place, keeping the same `naddr`/poster URL.
|
||||
- **Re-publish (keep-alive)** — re-sign and re-broadcast the current content so
|
||||
relays that prune app-data don't age the flyer out (`republishCurrentFlyer`).
|
||||
- **Delete** (`deleteLoadedFlyer`) — two layers, for robustness across relays:
|
||||
1. a **replaceable tombstone** (`buildTombstoneEvent`) — same `(kind, d)`, with
|
||||
`deleted: true` in the payload and a `["deleted"]` tag, so it *overwrites*
|
||||
the flyer's content; relays honoring replaceable semantics now serve the
|
||||
tombstone, and
|
||||
2. a **NIP-09 deletion request** (`buildDeletionEvent`, kind `5`) referencing
|
||||
the addressable `a` tag (`30078:<pubkey>:voxvera:<slug>`) and the event id,
|
||||
asking relays to drop it entirely.
|
||||
|
||||
All three are **author-only**: the active signing key must match the loaded
|
||||
flyer's author (`resolveActivePubkey`), and `signAndPublish` refuses to publish
|
||||
if the signed key diverges from the address. **Tombstone recognition:** the
|
||||
board's `parseFlyers` keeps the newest event per `(pubkey, d)` and skips it if
|
||||
that newest version is a tombstone (so a delete can't be undone by an older copy
|
||||
arriving later); the viewer shows a localized "This flyer was removed." state
|
||||
(`isFlyerTombstone`). Deletion is **best-effort** — relays that ignore both
|
||||
replaceable overwrites and NIP-09 may still serve the original — so it is framed
|
||||
as a request, not a guarantee.
|
||||
|
||||
## Importing and exporting a flyer design
|
||||
|
||||
The editor can save and load a flyer **design** as a portable `.json` file
|
||||
(`Export design` / `Import design`), independent of publishing. The file format
|
||||
is `{ type: "voxvera_flyer_design", version: 1, flyer: <payload>, relays: [] }`,
|
||||
where `flyer` is exactly `rawPayloadFromForm()` — the content fields plus the
|
||||
relay list, and **nothing identity-bound**: no npub, `naddr`, event id, or
|
||||
signature (all of those are derived at publish time by `withPosterUrl` /
|
||||
`signAndPublish`). That makes a design portable: it can be handed to anyone and
|
||||
published under *their* key with a fresh address.
|
||||
|
||||
- **Export** (`exportDesign`) serializes the current form as-is (draft-friendly,
|
||||
no strict validation) and downloads `<folder_name>-voxvera-design.json`.
|
||||
- **Import** (`importDesignFromFile`) reads the picked file (capped at 256 KB),
|
||||
`JSON.parse`s it, and accepts either the wrapper format or a bare
|
||||
`voxvera_flyer` payload (`readDesignFile`, lenient). It then shows a **confirm
|
||||
modal** (`#import-modal`) before overwriting the editor, and on confirm
|
||||
(`applyPendingImport`) fills the form via `fillEditorFromConfig` and restores
|
||||
the relay list. Imported content is untrusted, but it flows through the lenient
|
||||
view path (the renderer escapes every field) and still faces strict
|
||||
`validatePayload` at publish (raw-HTML rejection, length caps, URL schemes).
|
||||
|
||||
This replaced the earlier raw "Export event JSON" button; the published
|
||||
(signed) event JSON is still shown in `#event-json-output` after a publish.
|
||||
|
||||
## Print paper size
|
||||
|
||||
The flyer supports two print sizes: **US Letter** (8.5×11in) and **A4**
|
||||
(210×297mm), covering every country whose language the client supports (Letter
|
||||
in North America and a few Latin American countries; A4 everywhere else,
|
||||
including the EU, Russia, China, Japan, and the Middle East).
|
||||
|
||||
- Dimensions live in CSS custom properties `--sheet-w` / `--sheet-h`, switched
|
||||
by a `paper-letter` / `paper-a4` class on `<html>` (`applyPaperSize` in
|
||||
`nostr-client.js`). The tear-off column (`3.75in`) and QR codes (`1.25in`)
|
||||
stay fixed physical sizes; the content column flexes to the sheet width.
|
||||
- The print `@page { size: … }` is injected by JS (an element with id
|
||||
`voxvera-page-size`), because `@page size` cannot read CSS custom properties
|
||||
across engines. The static `@media print` block keeps `margin: 0` and a
|
||||
Letter default for the pre-JS state.
|
||||
- The default is chosen from the **region subtag** of the browser locale
|
||||
(`preferredPaperSize` — e.g. `en-GB` → A4, `en-US` → Letter). This is "by
|
||||
location" without geolocation, using the same signal as language. When no
|
||||
locale carries a region, it falls back to Letter.
|
||||
- A user override (the paper-size selector) is stored in `localStorage`
|
||||
(`voxvera_paper`) and wins over the region default.
|
||||
- **Paper size is a local print/view preference and is never written into the
|
||||
Nostr event.** A flyer authored on Letter reprints on A4 for a European
|
||||
viewer without changing the source event. The live fit-check protects
|
||||
authoring on whichever size is active; switching to a narrower size after
|
||||
authoring can ellipsis-truncate a maxed-out single-line field.
|
||||
|
||||
Field capacity therefore varies by paper size; see
|
||||
[`flyer-field-limits.md`](flyer-field-limits.md).
|
||||
|
||||
## Bulletin board
|
||||
|
||||
`site/board.html` + `site/board.js` are a standalone page that lists the most
|
||||
recent flyers found on the default relays as a sortable, spreadsheet-style
|
||||
table: **title**, **link** (the poster URL, rendered as the word "link"),
|
||||
**posting npub**, **language**, **posted date**, and the **event ID** (shown
|
||||
shortened, full value in the title attribute, with a per-row copy button). Any
|
||||
column header sorts (default is date descending); replaceable events are
|
||||
de-duplicated per author+`d` identifier, keeping the latest.
|
||||
|
||||
- The entry point is a small screen-only link below the flyer preview
|
||||
(`.board-link`, label `bulletin_board`), outside the printable sheet. It must
|
||||
never print (hidden in the `@media print` block alongside the other app
|
||||
chrome).
|
||||
- **The board is gated behind a connected Nostr identity.** On load it shows a
|
||||
login gate (`#board-gate`) instead of the table, with four ways to connect:
|
||||
a **NIP-07** extension (`window.nostr.getPublicKey()`), a **NIP-46 remote
|
||||
signer** (either paste a `bunker://` link or scan a `nostrconnect://` QR; same
|
||||
hand-rolled client as the editor — it establishes the viewer pubkey via
|
||||
`get_public_key` and keeps the connection so `getBoardSigner` can sign
|
||||
reports/deletes remotely this session, then falls back to read-only after a
|
||||
reload), **pasting an `nsec`** (decoded in-page to
|
||||
derive the pubkey, then discarded — the secret is never stored or transmitted),
|
||||
or **creating a new key** (reuses this device's anon key in
|
||||
`voxvera_nostr_anon_secret_hex` if present, else generates one, and reveals the
|
||||
`nsec` with a save-it warning before continuing). On success it reveals the
|
||||
table and surfaces the connected npub (`#board-identity`) with a Disconnect
|
||||
control. The board only ever needs the *pubkey* to view (it reads to filter),
|
||||
so the connected pubkey is remembered in `localStorage`
|
||||
(`voxvera_connected_pubkey`, shared with the main client) and a return visit
|
||||
reconnects from it directly — no prompt or re-entry, any method. This is
|
||||
**not access control** — the events are public on the relays regardless — it
|
||||
establishes the *viewer's* identity for the web-of-trust filter below.
|
||||
Authoring and printing flyers stays fully anonymous and never requires
|
||||
connecting.
|
||||
- **Web-of-trust filter (NIP-02).** Once connected, the board fetches the
|
||||
viewer's contact list (kind 3) and defaults to showing only flyers whose
|
||||
author is in the viewer's follow graph (degree 1) plus the viewer themself. A
|
||||
**"Show all"** checkbox opts out to the full relay firehose. A viewer with no
|
||||
follow list of their own (a fresh key) is **seeded** from a pinned curator
|
||||
account's follows (`FALLBACK_CURATOR_PUBKEY` in `board.js`), so a brand-new
|
||||
viewer still gets a curated board. If no trust data can be fetched at all, the
|
||||
board falls back to showing everything so it is never mysteriously empty. The
|
||||
`#board-filter-note` explains which mode is active (following / seeded / all),
|
||||
and re-localizes with the language selector. See [`roadmap.md`](roadmap.md)
|
||||
for the phased plan (Phase 1 = the gate; Phase 2 = this filter; Phase 3 =
|
||||
degree-2 trust, blocklist/report, NIP-05 badges).
|
||||
- `board.js` is independent of `nostr-client.js` (which exports nothing), so its
|
||||
UI strings live in `BOARD_UI` (all supported languages); it reuses the
|
||||
vendored nostr-tools and `locales.js` (for language names + RTL direction).
|
||||
- The board has its own language selector. It reads/writes the same
|
||||
`voxvera_nostr_lang` localStorage key as the main client, so the chosen
|
||||
language carries across both pages, and switching it re-localizes the chrome,
|
||||
column headers, language labels, and date formatting (and flips RTL).
|
||||
- Relay content is untrusted: titles and npubs are escaped, and link URLs are
|
||||
rejected unless `http:`/`https:` (so `javascript:`/`data:` never render as a
|
||||
link).
|
||||
- The npub column is forward-looking — anonymous keys today, but a stable
|
||||
identity per author maps cleanly onto this view later.
|
||||
- **Per-row actions** (behind a per-row **⋯ menu**). On flyers the connected
|
||||
viewer authored, the menu offers
|
||||
**Edit** (a link to `/?edit=1#<naddr>`, which loads the flyer in the editor),
|
||||
**Re-broadcast** (re-sends the already-signed event to all relays — no signing
|
||||
needed), and **Delete** (tombstone + NIP-09; the board signs via the device
|
||||
key or NIP-07, and for a pasted-nsec connection it points to the editor). On
|
||||
flyers from others it shows **Block** — a per-device blocklist of author
|
||||
pubkeys (`voxvera_blocked_pubkeys`) that always hides them, with a "Clear
|
||||
blocked" control. The blocklist is local "hide this," separate from the
|
||||
web-of-trust filter (roadmap #1).
|
||||
- **Narrow screens (≤640px):** the table collapses to a card per flyer — the
|
||||
**title** and the **⋯ menu** stay visible, and the secondary fields (link,
|
||||
posted-by, language, date, event id) sit behind a per-row **Details**
|
||||
disclosure (`.board-details-toggle` toggles `tr.expanded`; the columns become
|
||||
labeled rows via their `data-label`).
|
||||
|
||||
On mobile the flyer preview scales to fully fit the screen width
|
||||
(`updatePreviewScale` / `--flyer-preview-scale`): the sheet keeps its true print
|
||||
width (`flex: 0 0 auto`, so the viewer-mode flexbox doesn't shrink it) and is
|
||||
visually scaled with a transform — so it never side-scrolls or clips.
|
||||
|
||||
The login gate (Phase 1) and the web-of-trust filter (Phase 2) are in place.
|
||||
Remaining gaps — degree-2 trust, a blocklist/report flow, NIP-05 badges, and
|
||||
making the bootstrap curator configurable — are tracked in
|
||||
[`roadmap.md`](roadmap.md).
|
||||
|
||||
## Localization
|
||||
|
||||
Flyer defaults come from `site/locales.js`.
|
||||
|
||||
Nostr editor/viewer controls and Nostr-specific flyer labels come from `NOSTR_UI` in `site/nostr-client.js`.
|
||||
|
||||
Language changes should:
|
||||
|
||||
- publish the selected flyer language in payload `lang`
|
||||
- publish matching Nostr language tags
|
||||
- infer language from event tags if a fetched payload omits `lang`
|
||||
- update default flyer content while the flyer is still using default content
|
||||
- preserve user-authored or fetched event content
|
||||
- update editor/viewer tool labels
|
||||
- update printed side-tab labels
|
||||
- respect RTL direction metadata
|
||||
|
||||
### Letter-spacing by script
|
||||
|
||||
Flyer text uses tighter letter-spacing than the original design to fit more
|
||||
characters per line, but `letter-spacing` is not script-neutral, so it is
|
||||
applied per script via a policy class on the flyer `.container`
|
||||
(`LETTER_SPACING_POLICY` in `nostr-client.js`; `ls-full` / `ls-cjk` / `ls-none`
|
||||
rules and `--ls-*` variables in `nostr-client.css`):
|
||||
|
||||
- `full` — Latin, Cyrillic, Hebrew: reduced positive tracking on the display
|
||||
fields plus a slight negative on body/URL to reclaim line width.
|
||||
- `cjk` — Japanese, Chinese: tracking is clamped to `0` and never negative, so
|
||||
full-width glyphs do not overlap.
|
||||
- `none` — Arabic, Persian, Hindi: letter-spacing is turned off entirely. These
|
||||
are cursive or complex scripts where any tracking breaks the letter joins or
|
||||
detaches combining marks. (This also corrected the prior behavior, which
|
||||
applied the design's display tracking to every language unconditionally.)
|
||||
|
||||
When adding a language, classify its script in `LETTER_SPACING_POLICY` (default
|
||||
is `full`) and verify the headline, subtitle, and body render correctly in the
|
||||
browser.
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
node --check site/nostr-client.js
|
||||
pytest -q
|
||||
```
|
||||
|
||||
For UI work, also verify browser rendering and print output from a local static server.
|
||||
@@ -1,51 +0,0 @@
|
||||
# Platform Support Matrix
|
||||
|
||||
This file is the canonical human-readable summary of VoxVera's actual platform support posture.
|
||||
|
||||
The machine-readable companion file is [`support-matrix.json`](/home/user/Documents/GitHub/VoxVera/support-matrix.json).
|
||||
|
||||
## Support Tiers
|
||||
|
||||
- **Supported**: validated for persistent hidden-service hosting with documented recovery behavior.
|
||||
- **Beta**: feature-complete enough for broader testing, but not yet validated for production-grade recovery claims.
|
||||
- **Experimental**: may install or run, but is not yet validated for reliable background hidden-service hosting.
|
||||
- **Unsupported**: not currently a target for reliable hosting.
|
||||
|
||||
## Current Matrix
|
||||
|
||||
| Platform | Tier | Canonical Runtime Model | Distribution Surfaces | Notes |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| Linux CLI with `systemd --user` | Supported | System Tor or Tor Browser plus `onionshare-cli`, with recurring `systemd --user` timer recovery | `install.sh`, `voxvera-install.sh`, `pip/pipx`, Linux binary | Current reference implementation |
|
||||
| Docker CLI | Experimental | Containerized runtime with `VOXVERA_DIR=/flyers` and periodic `start-all` retries | Dockerfile, GHCR image | Needs end-to-end restart validation |
|
||||
| macOS CLI | Experimental | CLI runtime with `launchd` autostart path and external Tor/OnionShare dependencies | `install.sh`, `pip/pipx`, macOS binary, DMG | No validated recovery claim yet |
|
||||
| Windows CLI | Experimental | CLI runtime with Task Scheduler path and external Tor/OnionShare dependencies | `install.ps1`, Windows binary, Chocolatey | Binary naming and runtime model need cleanup |
|
||||
| Electron GUI | Experimental | GUI frontend over the CLI runtime | `gui/electron` | Must converge on shared runtime behavior |
|
||||
| Flatpak/AppImage/Homebrew/Chocolatey/Deb | Experimental | Distribution-only until runtime parity exists | packaging scripts/manifests | Package availability does not imply hosting parity |
|
||||
|
||||
## What "Supported" Means For VoxVera
|
||||
|
||||
To move a platform to **Supported**, VoxVera should have evidence for all of the following:
|
||||
|
||||
1. Fresh install works on a clean machine.
|
||||
2. Manual `build` and `serve` work.
|
||||
3. `.onionshare-session` survives rebuilds and restarts.
|
||||
4. Hosting returns after reboot or login.
|
||||
5. Hosting returns after a temporary offline period.
|
||||
6. Logs and status are inspectable with documented commands.
|
||||
7. The docs and release artifacts do not overstate capability.
|
||||
|
||||
## Promotion Rules
|
||||
|
||||
- Do not promote a package surface before the underlying runtime model is validated.
|
||||
- Do not call a platform "recommended" unless it is also `supported`.
|
||||
- If a platform lacks validated auto-recovery after reboot or network interruption, it must remain `experimental` or `beta`.
|
||||
|
||||
## Current Recommendation
|
||||
|
||||
If your goal is reliable Tor hidden-service hosting today, use the Linux CLI path and install the recurring recovery timer with:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
```
|
||||
|
||||
That is the current reference deployment model the rest of the platform work should converge toward.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# Uso Detalhado
|
||||
|
||||
Este guia cobre os fluxos de trabalho comuns da CLI. Veja `docs/docker.md` para instruções do Docker e `docs/templates.md` para modelos de panfletos disponíveis.
|
||||
|
||||
## Pré-requisitos
|
||||
|
||||
O VoxVera foi projetado para ser altamente portátil e requer dependências mínimas do sistema.
|
||||
|
||||
### 1. Binários Independentes (Recomendado)
|
||||
Você pode baixar binários independentes e sem dependências para o seu sistema operacional:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
Estes binários incluem tudo o que é necessário para executar o VoxVera (exceto o `onionshare-cli`).
|
||||
|
||||
### 2. Instalador de Linha Única
|
||||
Alternativamente, instale através do nosso script automatizado:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. Instalação Manual via Python
|
||||
Se preferir executar a partir do código-fonte:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## Passo a Passo
|
||||
|
||||
1. **Inicializar:** Execute `voxvera init` e siga as instruções. Você será solicitado a selecionar seu idioma primeiro.
|
||||
2. **Construir:** Gere os arquivos do panfleto. Cada construção cria automaticamente um `voxvera-portable.zip` na pasta do panfleto, permitindo que outros baixem a ferramenta completa diretamente do seu panfleto.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Servir:** Publique o panfleto via Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
Isso detecta automaticamente sua instância do Tor, inicia o OnionShare e escreve o endereço .onion gerado nos links destacáveis do panfleto.
|
||||
|
||||
## Suporte a Idiomas
|
||||
|
||||
O VoxVera é totalmente localizado. Você pode alterar sua preferência de idioma permanentemente usando o seletor interativo ou um atalho direto:
|
||||
|
||||
- **Seletor Interativo:** `voxvera lang`
|
||||
- **Atalho Direto:** `voxvera --lang pt` (define a preferência para português)
|
||||
|
||||
### Idiomas Suportados:
|
||||
- **Inglês:** `en`
|
||||
- **Espanhol:** `es` (alias: `--idioma`)
|
||||
- **Alemão:** `de` (alias: `--sprache`)
|
||||
- **Português:** `pt`
|
||||
|
||||
Você também pode forçar um idioma específico para um único comando sem alterar sua preferência permanente:
|
||||
- **Inglês:** `voxvera --lang en check`
|
||||
- **Português:** `voxvera --lang pt check`
|
||||
|
||||
Os panfletos gerados detectam automaticamente o idioma do navegador do visitante e alteram o texto da interface adequadamente.
|
||||
|
||||
## Gerenciamento de Servidores
|
||||
|
||||
Gerencie vários panfletos e suas identidades Tor a partir de um único menu interativo:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Recursos:
|
||||
- **--- Criar Novo Site/Panfleto ---**: Inicia a sequência completa de configuração.
|
||||
- **--- Iniciar Todos os Sites ---**: Inicia ou encerra todos os panfletos da sua frota de uma só vez.
|
||||
- **Status em Tempo Real**: Visualize URLs .onion ativas e indicadores de progresso de inicialização do Tor.
|
||||
- **Controle Individual**: Exportar para Zip sites específicos para ZIP ou exclua-os.
|
||||
|
||||
## Espelhamento Universal (Distribuição Viral)
|
||||
|
||||
Para garantir que o VoxVera permaneça acessível mesmo se os repositórios centrais forem censurados, cada panfleto atua como um espelho para a ferramenta.
|
||||
|
||||
Quando você hospeda um panfleto, o botão **"Baixar Ferramenta e Código"** na página inicial fornece um `voxvera-portable.zip` contendo:
|
||||
- O código-fonte completo e todos os idiomas suportados.
|
||||
- Todas as dependências Python (pré-vendidas).
|
||||
- Binários Tor multiplataforma.
|
||||
|
||||
Isso permite que qualquer pessoa que escaneie seu panfleto se torne um novo distribuidor da ferramenta VoxVera.
|
||||
|
||||
## Exportação e Backup
|
||||
|
||||
Faça backup de suas identidades Tor exclusivas (para que sua URL .onion nunca mude) ou mova seus panfletos para outra máquina.
|
||||
|
||||
- **Exportar um único site**: `voxvera export <nome_da_pasta>`
|
||||
- **Exportar todos os sites**: `voxvera export-all`
|
||||
|
||||
**Local de armazenamento:** Todas as exportações são salvas como arquivos ZIP em uma pasta chamada `voxvera-exports` no diretório inicial do usuário (`~/voxvera-exports/`) em todas as plataformas.
|
||||
|
||||
## Importação e Recuperação
|
||||
|
||||
Restaure toda a sua configuração em uma nova máquina movendo seus arquivos ZIP para `~/voxvera-exports/` e executando:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Portabilidade e Uso Offline
|
||||
|
||||
Se precisar executar o VoxVera em uma máquina sem acesso à internet, você pode "venderizar" as dependências primeiro:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
Isso baixa todas as bibliotecas Python necessárias para `voxvera/vendor/`. A ferramenta priorizará esses arquivos locais, permitindo que ela funcione sem `pip install`.
|
||||
|
||||
## Importação em Lote (JSON)
|
||||
|
||||
Para gerar panfletos em massa a partir de vários arquivos de configuração JSON, coloque-os no diretório `imports/` e execute:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## Como as URLs Funcionam
|
||||
|
||||
Cada panfleto tem duas URLs separadas:
|
||||
- **Link destacável** (gerado automaticamente): O endereço .onion onde o panfleto está hospedado.
|
||||
- **Link de conteúdo** (configurado pelo usuário): Uma URL externa apontando para um site, vídeo ou download.
|
||||
|
||||
Você não precisa inserir manualmente o endereço .onion; o VoxVera lida com isso automaticamente durante a fase de `serve`.
|
||||
@@ -1,270 +0,0 @@
|
||||
# Platform Parity Roadmap
|
||||
|
||||
This roadmap focuses on one question:
|
||||
|
||||
How do we expand VoxVera beyond Linux without overstating reliability, while still converging on real cross-platform parity for Tor hidden-service hosting?
|
||||
|
||||
## Strategic Principle
|
||||
|
||||
Parity is not a packaging milestone. It is a runtime-contract milestone.
|
||||
|
||||
Every platform must eventually implement the same hosting contract:
|
||||
|
||||
1. install VoxVera
|
||||
2. ensure Tor and OnionShare are available
|
||||
3. build site assets
|
||||
4. serve the hidden service
|
||||
5. preserve `.onionshare-session`
|
||||
6. recover hosting after reboot, login, suspend, or offline periods
|
||||
7. surface logs and status
|
||||
|
||||
Package formats should inherit that contract. They should not define independent behavior.
|
||||
|
||||
## Phase 0: Truth Alignment
|
||||
|
||||
Goal: bring repo claims, docs, and release posture into line with current reality.
|
||||
|
||||
Deliverables:
|
||||
|
||||
- canonical support matrix
|
||||
- machine-readable support declaration
|
||||
- installer/package warnings for experimental paths
|
||||
- README and docs aligned to the actual supported target
|
||||
|
||||
Definition of done:
|
||||
|
||||
- no docs imply parity that tests do not support
|
||||
- every platform surface has an explicit support tier
|
||||
- release artifacts are not treated as proof of hosting reliability
|
||||
|
||||
## Phase 1: Harden Linux As Reference
|
||||
|
||||
Goal: make Linux CLI with `systemd --user` the clearly defensible model that other platforms copy.
|
||||
|
||||
Work items:
|
||||
|
||||
1. Add `voxvera doctor` for runtime validation.
|
||||
- Check Tor reachability.
|
||||
- Check OnionShare availability.
|
||||
- Check `start-all` surfaces.
|
||||
- Check autostart timer installation.
|
||||
- Check host directories and session files.
|
||||
|
||||
2. Add `voxvera autostart status`.
|
||||
- Show service and timer files.
|
||||
- Show whether the timer is enabled.
|
||||
- Show next/last run timestamps if available.
|
||||
|
||||
3. Normalize Linux log/status guidance.
|
||||
- Document host log paths.
|
||||
- Document timer/service status commands.
|
||||
- Document expected recovery flow after reboot/network loss.
|
||||
|
||||
4. Validate restart behavior.
|
||||
- fresh install
|
||||
- first serve
|
||||
- reboot
|
||||
- suspend/resume if possible
|
||||
- temporary offline period followed by reconnect
|
||||
|
||||
Definition of done:
|
||||
|
||||
- Linux remains the only `supported` path until the above evidence exists and is documented.
|
||||
|
||||
## Phase 2: Platform Adapter Layer
|
||||
|
||||
Goal: stop encoding platform logic in ad hoc installer scripts.
|
||||
|
||||
Recommended structure:
|
||||
|
||||
- `voxvera/platforms/base.py`
|
||||
- `voxvera/platforms/linux.py`
|
||||
- `voxvera/platforms/macos.py`
|
||||
- `voxvera/platforms/windows.py`
|
||||
- `voxvera/platforms/docker.py`
|
||||
|
||||
Each adapter should define:
|
||||
|
||||
- support tier
|
||||
- Tor discovery strategy
|
||||
- OnionShare discovery strategy
|
||||
- state root
|
||||
- autostart installation strategy
|
||||
- autostart status strategy
|
||||
- log/status surface
|
||||
- known limitations
|
||||
|
||||
CLI surfaces to add:
|
||||
|
||||
- `voxvera doctor`
|
||||
- `voxvera platform-status`
|
||||
- `voxvera autostart`
|
||||
- `voxvera autostart status`
|
||||
- `voxvera autostart uninstall`
|
||||
|
||||
Definition of done:
|
||||
|
||||
- shell installers become thin wrappers over shared Python logic instead of owning runtime policy themselves
|
||||
|
||||
## Phase 3: Docker Beta Candidate
|
||||
|
||||
Goal: make Docker a coherent, testable deployment surface.
|
||||
|
||||
Decisions to settle:
|
||||
|
||||
- single-container runtime vs compose-based runtime
|
||||
- host Tor vs container Tor
|
||||
- log and state persistence model
|
||||
|
||||
Recommended direction:
|
||||
|
||||
- keep runtime state under one explicit volume root
|
||||
- document restart policy clearly
|
||||
- make health and recovery behavior observable
|
||||
|
||||
Validation checklist:
|
||||
|
||||
- container restart preserves onion identity
|
||||
- host reboot with restart policy restores hosting
|
||||
- state remains in mounted volume
|
||||
- logs remain inspectable
|
||||
|
||||
Promotion target:
|
||||
|
||||
- `experimental` -> `beta`
|
||||
|
||||
## Phase 4: macOS CLI
|
||||
|
||||
Goal: establish one honest CLI-based macOS hosting model before packaging.
|
||||
|
||||
Work items:
|
||||
|
||||
1. define Tor discovery strategy
|
||||
2. define OnionShare discovery/install strategy
|
||||
3. validate manual `build` + `serve`
|
||||
4. implement and validate `launchd` recovery
|
||||
5. document known limitations
|
||||
|
||||
Promotion target:
|
||||
|
||||
- remain `experimental` until `launchd` recovery is validated
|
||||
- move to `beta` only after login/reboot/offline recovery evidence exists
|
||||
|
||||
## Phase 5: Windows CLI
|
||||
|
||||
Goal: establish one canonical Windows runtime model before claiming package parity.
|
||||
|
||||
Work items:
|
||||
|
||||
1. unify binary naming across installer, Chocolatey, docs, and release assets
|
||||
2. define Tor discovery strategy
|
||||
3. define OnionShare discovery strategy
|
||||
4. validate manual `build` + `serve`
|
||||
5. implement Task Scheduler recovery path
|
||||
6. add Windows-specific status/log guidance
|
||||
|
||||
Promotion target:
|
||||
|
||||
- remain `experimental` until scheduled recovery and state persistence are proven
|
||||
- move to `beta` only after reboot/login/offline recovery evidence exists
|
||||
|
||||
## Phase 6: Electron GUI Convergence
|
||||
|
||||
Goal: make the GUI a frontend to the supported runtime, not a separate runtime.
|
||||
|
||||
Work items:
|
||||
|
||||
1. route the GUI through shared CLI/runtime surfaces
|
||||
2. reduce duplicated Tor startup behavior
|
||||
3. add visibility for:
|
||||
- Tor status
|
||||
- OnionShare status
|
||||
- hosting status
|
||||
- onion URL
|
||||
- logs
|
||||
4. make window-close behavior explicit and safe
|
||||
|
||||
Promotion target:
|
||||
|
||||
- GUI remains `experimental` until it stops diverging from the CLI runtime contract
|
||||
|
||||
## Phase 7: Package Surface Promotion
|
||||
|
||||
Goal: package formats should become trustworthy wrappers around validated runtimes.
|
||||
|
||||
Work items:
|
||||
|
||||
1. Debian package
|
||||
- declare actual runtime dependencies
|
||||
- validate install + host + recovery path
|
||||
|
||||
2. AppImage
|
||||
- decide whether it is distribution-only or a real hosting target
|
||||
|
||||
3. Homebrew
|
||||
- fix artifact URL/sha/version policy
|
||||
- clarify whether it installs a hosting target or just a CLI
|
||||
|
||||
4. Chocolatey
|
||||
- align artifact naming and installer semantics
|
||||
|
||||
5. Flatpak
|
||||
- decide whether Tor/OnionShare can be supported sanely in-sandbox
|
||||
|
||||
Rule:
|
||||
|
||||
- no package surface should be promoted above the support tier of its underlying runtime
|
||||
|
||||
## Testing Program
|
||||
|
||||
### 1. Unit tests
|
||||
|
||||
- config/state logic
|
||||
- autostart file generation
|
||||
- platform adapter selection
|
||||
|
||||
### 2. Mocked integration tests
|
||||
|
||||
- `serve`
|
||||
- `autostart`
|
||||
- `doctor`
|
||||
- `platform-status`
|
||||
|
||||
### 3. Platform smoke tests
|
||||
|
||||
- fresh install
|
||||
- build
|
||||
- serve
|
||||
- persist identity
|
||||
- restart
|
||||
- recover
|
||||
|
||||
Current smoke target names:
|
||||
|
||||
- `linux-cli`
|
||||
- `macos-cli`
|
||||
- `windows-cli`
|
||||
- `docker-cli`
|
||||
|
||||
These target names are contract-level validation entry points. Only `linux-cli` currently represents a supported hosting path; the others should be used to validate experimental posture and dependency discovery on their native platforms until their recovery behavior is proven.
|
||||
|
||||
### 4. Release checks
|
||||
|
||||
- support matrix is current
|
||||
- docs match support tiers
|
||||
- artifact names match scripts and package manifests
|
||||
|
||||
## Immediate Next Tasks
|
||||
|
||||
1. Add `voxvera doctor`.
|
||||
2. Add `voxvera autostart status`.
|
||||
3. Add the platform adapter scaffold.
|
||||
4. Capture Linux reboot/offline recovery validation steps in docs and CI notes.
|
||||
5. Pick Docker's canonical runtime model.
|
||||
6. Normalize Windows binary naming before further Windows work.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- claiming parity before recovery behavior is validated
|
||||
- treating package availability as support proof
|
||||
- maintaining separate runtime semantics in GUI vs CLI
|
||||
@@ -1,93 +0,0 @@
|
||||
# VoxVera Roadmap & Technical Specification (v0.2.0)
|
||||
|
||||
This document outlines the next major evolution of the VoxVera project, focusing on trust, social amplification, visual versatility, and network resilience.
|
||||
|
||||
---
|
||||
|
||||
## 1. Integrity & Trust (PGP Signing)
|
||||
**Goal:** Provide cryptographic proof that the `voxvera-portable.zip` provided by a flyer has not been tampered with by the hoster.
|
||||
|
||||
### Technical Requirements
|
||||
- **CLI:** Add `voxvera sign <folder_name>` command.
|
||||
- **Dependency:** Use a lightweight PGP implementation (e.g., `python-gnupg` or `pgpy`) to sign the portable ZIP.
|
||||
- **Storage:** Generate a `.sig` or `.asc` file alongside the ZIP in the `download/` folder.
|
||||
- **Web:** The landing page will look for `voxvera-portable.zip.asc`. If found, a **"Verified Source"** badge with the signer's Fingerprint will appear next to the download button.
|
||||
|
||||
### Implementation Phases
|
||||
1. **Phase 1:** Add PGP key generation/import logic to `voxvera init`.
|
||||
2. **Phase 2:** Update `build_assets` to optionally sign the generated ZIP.
|
||||
3. **Phase 3:** Update `index-master.html` to display verification status.
|
||||
|
||||
---
|
||||
|
||||
## 2. Nostr Integration (Social Amplification)
|
||||
**Goal:** Bridge the physical world (flyers) with the decentralized digital world (Nostr) by automatically broadcasting live .onion sites.
|
||||
|
||||
### Technical Requirements
|
||||
- **CLI:** Add `voxvera serve --nostr` flag.
|
||||
- **Workflow:** When a site goes live and the `.onion` URL is generated, the tool posts a "Flyer Event" to a list of configured Nostr relays.
|
||||
- **Identity:** Users can provide an existing NSEC or have VoxVera generate a "Flyer Identity" (new NPUB) for that specific server.
|
||||
- **Metadata:** Include tags for the flyer title, headline, and the `.onion` link.
|
||||
|
||||
### Implementation Phases
|
||||
1. **Phase 1:** Add `nostr` and `bech32` to the `vendor/` directory.
|
||||
2. **Phase 2:** Implement a background broadcast thread in `serve()`.
|
||||
3. **Phase 3:** Add "View on Nostr" links to the flyer footer.
|
||||
|
||||
---
|
||||
|
||||
## 3. The "Tear-off" Designer (Template Gallery)
|
||||
**Goal:** Expand the utility of VoxVera to new use cases like missing person alerts, protest organizing, and artistic distribution.
|
||||
|
||||
### Technical Requirements
|
||||
- **Restructuring:** Move from a single `voxvera` template to a category-based system:
|
||||
- `/templates/default/` (The original Operation VoxVera style)
|
||||
- `/templates/minimal/` (Clean, text-heavy)
|
||||
- `/templates/alert/` (High-contrast, for emergencies)
|
||||
- `/templates/art/` (Image-focused)
|
||||
- **CLI:** Update `voxvera init` to include a visual description and selector for templates.
|
||||
|
||||
### Implementation Phases
|
||||
1. **Phase 1:** Refactor `copy_template` to support categories.
|
||||
2. **Phase 2:** Design and implement 3 new HTML/CSS templates.
|
||||
3. **Phase 3:** Allow templates to define their own custom character limits (e.g., "Alert" might allow larger headlines).
|
||||
|
||||
---
|
||||
|
||||
## 4. Self-Healing Network (Update Logic)
|
||||
**Goal:** Ensure the decentralized "Viral" network stays current with security fixes and features.
|
||||
|
||||
### Technical Requirements
|
||||
- **Discovery:** The tool will check a "Source of Truth" (e.g., `voxvera.org/version.json` or a hardcoded list of onion mirrors).
|
||||
- **Notification:** `voxvera manage` will show a 🌟 or ⚠️ next to the version number if an update is available.
|
||||
- **Update Workflow:** Provide a `voxvera update` command that downloads the latest `voxvera-portable.zip` and safely replaces the `vendor/` and `voxvera/` directories.
|
||||
|
||||
### Implementation Phases
|
||||
1. **Phase 1:** Implement version-checking logic via Tor SOCKS proxy.
|
||||
2. **Phase 2:** Add update notifications to the management menu.
|
||||
3. **Phase 3:** (Advanced) Implement "In-Place" updates for the vendored dependencies.
|
||||
|
||||
---
|
||||
|
||||
## 5. GUI Modernization
|
||||
**Goal:** Transition the Electron wrapper from a CLI mirror to a rich, visual dashboard.
|
||||
|
||||
### Technical Requirements
|
||||
- **Flyer Cards:** Replace the text list with visual "cards" showing the flyer's headline and a mini QR preview.
|
||||
- **Tor Dashboard:** A dedicated tab showing all active hidden services, their uptime, and their `.onion` links.
|
||||
- **One-Click Actions:** Visual buttons for "Export All," "Start All," and "New Flyer."
|
||||
- **Direct Log Stream:** A collapsible panel to see the OnionShare logs in real-time.
|
||||
|
||||
### Implementation Phases
|
||||
1. **Phase 1:** Update the IPC bridge between Electron and the Python CLI.
|
||||
2. **Phase 2:** Redesign the frontend using a modern, dark-themed CSS framework (keeping it local-first).
|
||||
3. **Phase 3:** Add a "Theme Preview" during the flyer creation process.
|
||||
|
||||
---
|
||||
|
||||
## Summary of Impact
|
||||
By completing this roadmap, VoxVera moves from a standalone utility to a **Decentralized Information Ecosystem**.
|
||||
- **Security** is solved via PGP.
|
||||
- **Reach** is solved via Nostr.
|
||||
- **Versatility** is solved via the Template Gallery.
|
||||
- **Sustainability** is solved via Update Logic.
|
||||
+340
@@ -0,0 +1,340 @@
|
||||
# VoxVera Roadmap & Known Issues
|
||||
|
||||
This document captures known limitations and the development directions that
|
||||
would address them. None of these are code bugs — they are product- and
|
||||
threat-model-level gaps in the current static Nostr client. They are listed
|
||||
roughly in priority order: the trust model (#1–#2) is the highest-leverage area
|
||||
because almost every other risk flows from it being undefined.
|
||||
|
||||
Status legend: **Open** (not started) · **Partial** (some mitigation exists) ·
|
||||
**Planned** (committed direction) · **In progress** (partially shipped).
|
||||
|
||||
## Shipped so far (2026-06-10)
|
||||
|
||||
The trust model (#1–#2) has moved from undefined to implemented:
|
||||
|
||||
- **Bulletin board login gate** — viewing the board requires a connected Nostr
|
||||
identity (NIP-07 extension, a pasted `nsec`, or a generated key).
|
||||
- **Web-of-trust filter (degree-2)** — the board defaults to flyers from authors
|
||||
in the viewer's NIP-02 follow graph *and the people those follows follow*
|
||||
(follows-of-follows), seeded from a curator account for fresh keys, with a
|
||||
"Show all" opt-out (so it is no longer an unmoderated firehose).
|
||||
- **Editor↔board identity sync** — a deliberate editor identity choice (NIP-07,
|
||||
imported/generated/unlocked nsec, or anonymous) is shared with the board via a
|
||||
local pubkey, so the same person sees a consistent identity across both pages.
|
||||
- **Editor publishing identity** — authors can publish anonymously (default),
|
||||
via NIP-07, or with an imported `nsec` that is optionally PIN-encrypted at
|
||||
rest (PBKDF2 → AES-GCM; plaintext never stored).
|
||||
- **Flyer management (edit / re-publish / delete)** — an author can edit a
|
||||
loaded flyer (re-publish replaces in place via the `d` tag), re-publish as a
|
||||
keep-alive, or delete it. Delete is belt-and-suspenders: a replaceable
|
||||
**tombstone** (so the board/viewer hide it even on relays that ignore NIP-09)
|
||||
plus a **NIP-09** deletion request. Best-effort, author-only. These actions are
|
||||
available in the editor and inline on the bulletin board (Edit / Re-broadcast /
|
||||
Delete on your own rows).
|
||||
- **Local blocklist** — a per-device "Block" on the board hides flyers from any
|
||||
author you didn't post (separate from the web-of-trust filter), with a clear
|
||||
control. This is the local blocklist direction from #1.
|
||||
- **Report (NIP-56)** — a board "Report" action on others' flyers publishes a
|
||||
signed **kind-1984** report (category + optional reason) referencing the flyer
|
||||
(`e`) and author (`p`), so other clients and moderators can aggregate it.
|
||||
Reporting also hides the flyer locally (pairs with the blocklist).
|
||||
- **Author display names** — the board shows each author's kind-0 display name
|
||||
(falling back to the npub), so flyers aren't labeled by bare keys. (NIP-05
|
||||
*verification* is still a future addition.)
|
||||
- **"My flyers" filter** — a board toggle to show only the connected user's own
|
||||
flyers (overrides the trust filter, since your own may not be in your graph).
|
||||
|
||||
All of the above is localized across the 14 languages and covered by the
|
||||
cross-engine Playwright suite. **What remains** on #1–#2 is polish (NIP-05
|
||||
badges, an identified-vs-anonymous display) plus
|
||||
the editor follow-ups noted under the *Planned direction* section. **#3–#5 are
|
||||
still fully open** — distribution centralization (#3) is now the
|
||||
highest-leverage untouched item.
|
||||
|
||||
---
|
||||
|
||||
## 1. Bulletin board has no moderation or abuse story — **In progress**
|
||||
|
||||
> Direction agreed and **Phases 1–2 shipped**: the board requires a connected
|
||||
> Nostr identity to view, and it now filters to flyers from the viewer's NIP-02
|
||||
> web of trust (with a bootstrap seed for new keys). See *Planned direction:
|
||||
> identity + web-of-trust on the board* below (jointly addresses #1 and #2).
|
||||
> Remaining: NIP-05 badges (Phase 3). Degree-2 trust + NIP-56 report shipped.
|
||||
|
||||
|
||||
**Problem.** `board.html` lists every Nostr event tagged `t=voxvera` / `t=flyer`
|
||||
from the public default relays, with no filtering, verification, or moderation.
|
||||
Anyone can publish a kind-`30078` event with those tags and immediately appear
|
||||
on the board — including spam, hostile titles, or links to harmful content, all
|
||||
under VoxVera's branding.
|
||||
|
||||
**Current mitigation (Partial on safety, not abuse).** Relay content is treated
|
||||
as untrusted: titles and npubs are HTML-escaped, and link URLs are rejected
|
||||
unless `http(s)` (so `javascript:`/`data:` never render). This prevents script
|
||||
injection but does nothing about spam or unwanted-but-valid content.
|
||||
|
||||
**Why it matters.** A static client cannot rate-limit or moderate server-side,
|
||||
so the board is trivially gameable the moment it is used adversarially. This is
|
||||
the single biggest liability for promoting the board publicly.
|
||||
|
||||
**Possible directions.**
|
||||
- Client-side curation: an allowlist of npubs (a "follows"/featured set) so the
|
||||
default view shows only vetted authors.
|
||||
- A local, user-controlled blocklist / "hide this" with `localStorage`
|
||||
persistence (per-device, no server needed). **✅ Shipped** — the board's
|
||||
per-row **Block** (`voxvera_blocked_pubkeys`).
|
||||
- A dedicated VoxVera relay (or relay set) that applies its own admission
|
||||
policy, with the public relays as fallback.
|
||||
- A "report" affordance that records to a relay/list a curator can act on.
|
||||
- Make the unfiltered firehose an explicit opt-in mode, not the default.
|
||||
|
||||
Depends on **#2** (without identity, allowlists/blocklists are weak).
|
||||
|
||||
## 2. Anonymous keys give no authenticity or accountability — **In progress**
|
||||
|
||||
> Phases 1–2 shipped: the board viewer connects a real Nostr identity (NIP-07)
|
||||
> and the board is filtered by that viewer's web of trust (with a curator seed
|
||||
> for new keys), so spam from unknown authors is hidden by default. The **editor
|
||||
> now lets authors publish under their own identity too** — NIP-07, an imported
|
||||
> `nsec` (optionally PIN-encrypted at rest), or stay anonymous (default) — so a
|
||||
> flyer can carry a stable, identifiable author when the creator wants one.
|
||||
> Authenticity *display* on the board (NIP-05 badges, an identified/anonymous
|
||||
> distinction) remains ahead.
|
||||
|
||||
**Problem.** The client generates a fresh anonymous key per browser, so the
|
||||
board's "Posted by" npub is effectively random and there is no way to verify a
|
||||
flyer came from who it claims. The trust model is currently empty.
|
||||
|
||||
**Why it matters.** Authenticity underpins the board, "report"/blocklist
|
||||
features, and any notion of a trusted author. Without stable identity, #1 has no
|
||||
foundation to build on.
|
||||
|
||||
**Possible directions.**
|
||||
- Optional persistent identity: let a user keep/reuse a key (or import one) and
|
||||
associate it with their flyers, while keeping anonymous-by-default.
|
||||
- First-class NIP-07 support for users who already have a Nostr identity.
|
||||
- Optional NIP-05 / verified handle display on the board.
|
||||
- A clear UI distinction between "anonymous" and "identified" flyers.
|
||||
|
||||
The npub column on the board was built deliberately forward-looking so this
|
||||
maps in cleanly.
|
||||
|
||||
## Planned direction: identity + web-of-trust on the board
|
||||
|
||||
Jointly addresses #1 and #2. The goal is to make the board accountable without
|
||||
abandoning anonymous-by-default authoring.
|
||||
|
||||
**Key reality that shapes the design.** You cannot gate *writing* to public
|
||||
relays — anyone can publish a `t=voxvera` event directly, never touching this
|
||||
client. So a "login required to post" button is only a soft deterrent; it can't
|
||||
bound what is on the board. The real lever is **filtering what the board
|
||||
displays**. Login's actual job is to supply the *viewer's* identity so the
|
||||
board can show them flyers from people they trust.
|
||||
|
||||
**Principles.**
|
||||
- **Login enables a trust-filtered view; it is not access control.** The data
|
||||
is public on relays regardless, so hiding it in the UI is cosmetic. Treat
|
||||
login as "we know who you are, so we can show you a trustworthy board."
|
||||
- **Keep anonymous creation + printing fully available.** The core authoring
|
||||
tool must not require a persistent, linkable identity (activist threat model).
|
||||
Identity is required only to *appear on the public board*, not to make/print a
|
||||
flyer.
|
||||
- **Web-of-trust is the actual spam defense, not login.** NIP-07 keys are free
|
||||
and unlimited, so "must have a key" alone just makes a spammer generate one.
|
||||
Filtering by the viewer's NIP-02 follow graph (degree 1, optionally
|
||||
follows-of-follows) is what raises the cost.
|
||||
- **Don't lock out mobile.** NIP-07 (`window.nostr`) needs a desktop extension,
|
||||
but scanned-QR flyers open on phones. "Login" should support NIP-07 **plus**
|
||||
nsec import (with warnings) and/or NIP-46 remote signer, and/or promoting the
|
||||
existing anonymous key to a kept identity.
|
||||
|
||||
**Phased plan.**
|
||||
- **Phase 1 — Identity. ✅ Shipped.** The board (`board.html` / `board.js`) shows
|
||||
a login gate instead of the table until the viewer connects. Three methods: a
|
||||
NIP-07 extension (`window.nostr.getPublicKey()`), pasting an `nsec`, or creating
|
||||
a new key (see decision 2 below). On success it reveals the table, surfaces the
|
||||
connected npub with a Disconnect control, and remembers the pubkey in
|
||||
`localStorage` (`voxvera_connected_pubkey`) so a return visit reconnects from
|
||||
the pubkey alone — no prompt or re-entry, regardless of method. Anonymous
|
||||
create/print is untouched — connecting is required only to *view the board*.
|
||||
- **Phase 2 — Web-of-trust filter. ✅ Shipped.** On connect the board fetches
|
||||
the viewer's NIP-02 contact list (kind 3) and defaults to flyers from authors
|
||||
in their follow graph (degree 1) plus themselves, with a **"Show all"**
|
||||
opt-out. **Bootstrap seed:** a viewer with no follow list of their own (a
|
||||
fresh key) is seeded from a pinned curator account's follows
|
||||
(`FALLBACK_CURATOR_PUBKEY` in `board.js` =
|
||||
`npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx`), so a brand-
|
||||
new viewer still gets a curated board instead of the unmoderated firehose. If
|
||||
no trust data can be fetched at all, the board falls back to showing
|
||||
everything (never mysteriously empty). Covered by the cross-engine e2e suite
|
||||
(followed-only view + show-all opt-out; curator-seeded fallback).
|
||||
- **Phase 3 — In progress.** Degree-2 trust (follows-of-follows) ✅ shipped; the
|
||||
local blocklist / "hide this" ✅ shipped; NIP-56 reporting (kind 1984) ✅
|
||||
shipped. **Remaining:** NIP-05 verified badges, and a curator-side flow that
|
||||
*consumes* reports (today a report is published for others to aggregate, but
|
||||
the board does not yet act on report counts). Also: the bootstrap curator is a
|
||||
single hardcoded pubkey — consider making it configurable or a small set.
|
||||
|
||||
**Decisions made (2026-06-10).**
|
||||
1. **Board viewing: login-required.** The board is blank (a Connect prompt)
|
||||
until a Nostr identity is connected — framed as a members' space rather than a
|
||||
public discovery surface.
|
||||
2. **Login methods: NIP-07 + nsec import + key generation. ✅ Shipped.** The gate
|
||||
offers three ways in: a NIP-07 browser extension, pasting a private key
|
||||
(`nsec`), or creating a new key. The nsec is decoded **in-page** to derive the
|
||||
pubkey and then discarded — only the pubkey is persisted, since the board only
|
||||
reads (never signs). "Create a new key" reuses this device's existing
|
||||
anonymous key if present (so it doesn't orphan an editor identity) or
|
||||
generates one, and reveals the `nsec` with a "save this — we can't recover it"
|
||||
warning before continuing. This **resolves the earlier mobile-lockout
|
||||
trade-off**: a phone visitor with no extension can now generate or paste a key
|
||||
to view the board. Covered by the cross-engine e2e suite (nsec import +
|
||||
pubkey-only persistence + reload restore; invalid nsec; key generation +
|
||||
reveal + connect).
|
||||
|
||||
**Follow-ups this opens.**
|
||||
- **In-page nsec handling.** Pasting a secret key into a web page is inherently
|
||||
riskier than a NIP-07 extension that keeps the key isolated; the input is a
|
||||
password field, the value is cleared after use, and nothing is transmitted. The
|
||||
**NIP-46 remote signer** (below) is now the safer mobile path.
|
||||
- **NIP-46 remote signer (shipped — editor *and* board, both connect paths).**
|
||||
Both the editor's publishing identity and the board's login gate can connect a
|
||||
remote signer two ways: **(a) `bunker://`** — paste a link the signer app
|
||||
generated; and **(b) `nostrconnect://` (QR)** — *we* generate the link, show it
|
||||
as a QR (and a copyable link for one-device use), and the signer app scans it
|
||||
and connects back (verified by echoing our secret). Either way the user's
|
||||
secret stays in their signer app (nsec.app, Amber, …) and the browser holds
|
||||
only an ephemeral local key. The client is hand-rolled over a raw WebSocket
|
||||
using the vendored NIP-44 (with a NIP-04 decrypt fallback) — the bundle ships
|
||||
no nip46 module; the QR flow uses `relay.nsec.app` as the rendezvous relay. On
|
||||
the board it establishes the viewer pubkey and keeps the connection so
|
||||
reports/deletes are signed remotely (read-only after a reload). Connections are
|
||||
**session-only** (nothing is written to disk, so a reload returns to anonymous
|
||||
/ read-only). Covered by the cross-engine e2e suite for both paths on both
|
||||
pages (bunker and nostrconnect), against a fake signer doing real NIP-44
|
||||
crypto.
|
||||
- **Editor identity (shipped).** The editor signs under anon / NIP-07 / imported
|
||||
nsec / remote signer. A remembered nsec is PIN-encrypted at rest (PBKDF2 600k →
|
||||
AES-GCM); plaintext is never stored. **Known weakness:** a short numeric PIN is
|
||||
brute-forceable offline if the encrypted blob leaks — it guards casual snooping,
|
||||
not a targeted attacker. A **wrong-PIN lockout** is now in place (3 bad PINs →
|
||||
a 30s cooldown, persisted across reloads). Optionally encrypting the anonymous
|
||||
device key the same way is still open (today it is stored in plaintext, as
|
||||
before).
|
||||
- **Editor↔board identity sync (shipped).** A deliberate editor identity choice
|
||||
(NIP-07 / imported / generated / unlocked nsec / remote signer) writes a shared
|
||||
local pubkey the board reads, so one connected identity is reflected across both
|
||||
pages.
|
||||
|
||||
## 3. Client distribution is centralized (a single chokepoint) — **Open**
|
||||
|
||||
**Problem.** The content lives on decentralized relays, but the *client* is one
|
||||
domain (`voxvera.org`) on a centralized host (Vercel). A censor can block the
|
||||
domain and most users are stuck, which undercuts the censorship-resistance
|
||||
premise even though the backend is robust.
|
||||
|
||||
**Current mitigation (Partial).** The client is fully static and host-agnostic,
|
||||
so it *can* be served from any static host or mirror — but discovery and trust
|
||||
of mirrors is unsolved, so in practice users depend on the canonical domain.
|
||||
|
||||
**Possible directions.**
|
||||
- Document and support official mirrors (IPFS/IPNS, other static hosts) with a
|
||||
verifiable build (subresource integrity / reproducible hash).
|
||||
- A one-file/offline build users can save and reopen (`file://`) — verify
|
||||
WebCrypto/clipboard degrade gracefully off a secure context.
|
||||
- Revisit the dropped Tor/onion distribution path as an *optional* mirror (kept
|
||||
off `main` per current guardrails, but a documented option).
|
||||
- Publish the client itself to a content-addressed network so the front door is
|
||||
not a single DNS name.
|
||||
|
||||
## 4. Relay permanence is overstated — **Partial**
|
||||
|
||||
> Partial mitigation shipped: the editor now has a **Re-publish (keep-alive)**
|
||||
> action, so an author can refresh a flyer before relays age it out. The durable
|
||||
> fix (a pinned/dedicated relay) is still open.
|
||||
|
||||
**Problem.** The app depends on a few general-purpose relays
|
||||
(`relay.damus.io`, `nos.lol`, `relay.primal.net`) that can prune app-data kinds,
|
||||
rate-limit, or drop events. "Your flyer is still there later" is therefore not
|
||||
guaranteed. The single relay hint in the `naddr` also reduces fetch robustness
|
||||
for events not on the default set.
|
||||
|
||||
**Possible directions.**
|
||||
- Run/pin a dedicated VoxVera relay (or several) so published flyers have a
|
||||
durable home, with the public relays as redundancy.
|
||||
- Let authors configure and embed their own preferred relays.
|
||||
- Consider a re-broadcast / "keep alive" helper for important flyers.
|
||||
- Reconsider how many relay hints to embed in the poster `naddr` (tradeoff:
|
||||
URL length / QR density vs. fetch robustness — see the QR Target notes in the
|
||||
spec).
|
||||
- **Self-contained fallback payload in the URL fragment (future).** Because a
|
||||
printed flyer cannot be edited, a pruned/unreachable event leaves a dead QR.
|
||||
The flyer payload is small (text only), so it could be compressed and encoded
|
||||
into the URL `#fragment` alongside the `naddr`, letting the viewer render the
|
||||
flyer *even when no relay has the event* — relay-independent durability, which
|
||||
fits the censorship-resistance pitch. **Constraint:** the tear-off QR URL is
|
||||
already near scannable capacity, so this likely can't be added without
|
||||
reducing the number of tear-off tabs and/or enlarging the QR (denser code,
|
||||
harder scan). Best treated as an opt-in "durable QR" mode rather than the
|
||||
default, and decided alongside the tab-count/QR-size tradeoff. The `naddr`
|
||||
remains the primary resolver; the embedded payload is a last-resort fallback.
|
||||
|
||||
## 5. Content-safety guardrails are minimal — **Open**
|
||||
|
||||
**Problem.** Beyond HTML-escaping and URL-scheme rejection, there is nothing
|
||||
preventing the tool (and especially the public board) from being used to author
|
||||
or surface illegal/harmful content carrying VoxVera's branding.
|
||||
|
||||
**Possible directions.** Tie this to #1/#2: curation, reporting, and a clear
|
||||
terms/acceptable-use stance for any hosted board. A purely local authoring tool
|
||||
has a smaller surface than a public discovery board, so scope decisions here
|
||||
should follow the board's trust model.
|
||||
|
||||
---
|
||||
|
||||
## Smaller / lower-priority items
|
||||
|
||||
- **Field-fit is layout-measured, not a fixed cap.** Robust, but capacity
|
||||
varies with font availability and zoom; the
|
||||
[cheat sheet](flyer-field-limits.md) is explicitly approximate. Fine as-is;
|
||||
noted so it is not mistaken for a contract.
|
||||
- **Favicon — ✅ done.** A small inline SVG (`site/favicon.svg`) is linked from
|
||||
both pages, so browsers no longer request (and 404 on) `/favicon.ico`.
|
||||
- **i18n key-parity guard — ✅ done.** `e2e/i18n.spec.js` fails if any
|
||||
`NOSTR_UI` / `BOARD_UI` / `SAFETY_UI` / locales dictionary is missing (or has
|
||||
an extra) key in some language (and that the `SAFETY_UI` bullet lists are the
|
||||
same length in every language). It immediately caught `field_too_long`, which
|
||||
had been English-only across all 13 other languages.
|
||||
- **Safety & privacy page — ✅ done.** A standalone `/safety` page
|
||||
(`safety.html` / `safety.js`), localized across all 14 languages, in plain
|
||||
language: what VoxVera protects, what it does **not** (relays see your IP; the
|
||||
anon key is plaintext in the browser; a short PIN won't stop a targeted
|
||||
attacker; published events are public/permanent; nsec-paste risk; reports are
|
||||
public; the host/relays still see requests), and operational tips (Tor/VPN,
|
||||
disposable keys, signer apps). Linked from the editor and the board. Aimed at
|
||||
the activist/whistleblower audience the aesthetic invites — being honest about
|
||||
limits matters more than any feature.
|
||||
- **Link previews / Open Graph — shipped (site-wide).** Static OG +
|
||||
Twitter-card meta are on the home, board, and safety pages, including a
|
||||
**1200×630 preview image** (`site/og-card.jpg`, `summary_large_image`), so a
|
||||
shared `voxvera.org` link renders a real title, description, and image card.
|
||||
**Per-flyer previews remain a deliberate non-goal:** the poster `naddr` lives
|
||||
in the URL `#fragment` (invisible to servers), and a static host can't render
|
||||
per-flyer `<meta>`/image without server-side code — out of scope by choice
|
||||
(this stays a free, purely static site). Revisit only if that constraint ever
|
||||
changes.
|
||||
- **Publish transparency — ✅ done.** The publish confirmation modal now reports
|
||||
how many relays accepted the event ("Relays accepted: N / M") and flags a
|
||||
zero-acceptance publish, so a weak publish is visible immediately.
|
||||
- **WebKit/Safari coverage in CI** needs `libavif16` on Linux runners
|
||||
(`sudo npx playwright install-deps`); headless WebKit is also not a perfect
|
||||
stand-in for real Safari/iOS print + clipboard behavior, so a real-device
|
||||
pass before releases is still worth it.
|
||||
|
||||
---
|
||||
|
||||
*Reviewed 2026-06-10. The trust model (#1–#2) is now implemented — see "Shipped
|
||||
so far" above. The highest-leverage untouched item is now #3 (the client is a
|
||||
single centralized domain), since it most undercuts the censorship-resistance
|
||||
premise even with the backend on decentralized relays.*
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# Подробное руководство
|
||||
|
||||
Это руководство охватывает основные рабочие процессы CLI. См. `docs/docker.md` для инструкций по Docker и `docs/templates.md` для доступных шаблонов листовок.
|
||||
|
||||
## Предварительные требования
|
||||
|
||||
VoxVera разработан как высокопортативный инструмент и требует минимум системных зависимостей.
|
||||
|
||||
### 1. Автономные бинарные файлы (Рекомендуется)
|
||||
Вы можете скачать автономные исполняемые файлы без зависимостей для вашей операционной системы:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
Эти файлы включают все необходимое для запуска VoxVera (кроме `onionshare-cli`).
|
||||
|
||||
### 2. Однострочный установщик
|
||||
Или установите с помощью нашего автоматического скрипта:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. Ручная установка через Python
|
||||
Если вы предпочитаете запускать из исходного кода:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## Шаг за шагом
|
||||
|
||||
1. **Инициализация:** Запустите `voxvera init` и следуйте подсказкам. Вам будет предложено сначала выбрать язык.
|
||||
2. **Сборка:** Сгенерируйте ресурсы листовки. Каждая сборка автоматически создает файл `voxvera-portable.zip` в папке листовки, позволяя другим скачивать полный инструмент прямо с вашей листовки.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Запуск:** Опубликуйте листовку через Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
Это автоматически обнаружит ваш экземпляр Tor, запустит OnionShare и запишет сгенерированный .onion адрес в отрывные ссылки листовки.
|
||||
|
||||
## Поддержка языков
|
||||
|
||||
VoxVera полностью локализован. Вы можете изменить свои языковые предпочтения навсегда, используя интерактивный селектор или прямой ярлык:
|
||||
|
||||
- **Интерактивный селектор:** `voxvera lang`
|
||||
- **Прямой ярлык:** `voxvera --lang ru` (устанавливает русский язык)
|
||||
|
||||
### Поддерживаемые языки:
|
||||
- **Английский:** `en`
|
||||
- **Испанский:** `es` (алиас: `--idioma`)
|
||||
- **Немецкий:** `de` (алиас: `--sprache`)
|
||||
- **Русский:** `ru`
|
||||
|
||||
Вы также можете принудительно использовать определенный язык для одной команды, не меняя постоянные настройки:
|
||||
- **Английский:** `voxvera --lang en check`
|
||||
- **Русский:** `voxvera --lang ru check`
|
||||
|
||||
Сгенерированные листовки автоматически определяют язык браузера посетителя и соответствующим образом переключают текст интерфейса.
|
||||
|
||||
## Управление серверами
|
||||
|
||||
Управляйте несколькими листовками и их Tor-идентификаторами из единого интерактивного меню:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Возможности:
|
||||
- **--- Создать новый сайт/листовку ---**: Запуск полной последовательности настройки.
|
||||
- **--- Запустить все сайты ---**: Запуск или остановка всех листовок в вашем парке одновременно.
|
||||
- **Статус в реальном времени**: Просмотр активных .onion URL и индикаторов прогресса загрузки Tor.
|
||||
- **Индивидуальный контроль**: Экспорт в Zip определенных сайтов в ZIP или их удаление.
|
||||
|
||||
## Универсальное зеркалирование (Вирусное распространение)
|
||||
|
||||
Чтобы VoxVera оставался доступным, даже если центральные репозитории будут подвергнуты цензуре, каждая листовка выступает в качестве зеркала для инструмента.
|
||||
|
||||
Когда вы хостите листовку, кнопка **"Скачать инструмент и код"** на целевой странице предоставляет `voxvera-portable.zip`, содержащий:
|
||||
- Полный исходный код и все поддерживаемые языки.
|
||||
- Все зависимости Python (пре-вендоризованные).
|
||||
- Кроссплатформенные бинарные файлы Tor.
|
||||
|
||||
Это позволяет любому, кто сканирует вашу листовку, стать новым распространителем инструмента VoxVera.
|
||||
|
||||
## Экспорт и резервное копирование
|
||||
|
||||
Создавайте резервные копии своих уникальных Tor-идентификаторов (чтобы ваш .onion URL никогда не менялся) или переносите листовки на другую машину.
|
||||
|
||||
- **Экспорт одного сайта**: `voxvera export <имя_папки>`
|
||||
- **Экспорт всех сайтов**: `voxvera export-all`
|
||||
|
||||
**Место хранения:** Все экспорты сохраняются в виде ZIP-файлов в папке `voxvera-exports` в домашнем каталоге пользователя (`~/voxvera-exports/`) на всех платформах.
|
||||
|
||||
## Импорт и восстановление
|
||||
|
||||
Восстановите всю свою настройку на новой машине, переместив ZIP-файлы в `~/voxvera-exports/` и запустив:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Портативность и работа оффлайн
|
||||
|
||||
Если вам нужно запустить VoxVera на машине без доступа к Интернету, вы можете сначала «вендоризовать» зависимости:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
Это загрузит все необходимые библиотеки Python в `voxvera/vendor/`. Инструмент будет отдавать приоритет этим локальным файлам, что позволит ему работать без `pip install`.
|
||||
|
||||
## Пакетный импорт (JSON)
|
||||
|
||||
Чтобы массово генерировать листовки из нескольких конфигурационных файлов JSON, поместите их в директорию `imports/` и запустите:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## Как работают URL-адреса
|
||||
|
||||
У каждой листовки есть два отдельных URL-адреса:
|
||||
- **Отрывная ссылка** (автоматически генерируется): .onion адрес, по которому размещена листовка.
|
||||
- **Ссылка на контент** (настраивается пользователем): Внешний URL, указывающий на веб-сайт, видео или загрузку.
|
||||
|
||||
Вам не нужно вручную вводить .onion адрес; VoxVera обрабатывает это автоматически на этапе `serve`.
|
||||
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `cli.token_name` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
@@ -1,14 +0,0 @@
|
||||
# Flyer Templates
|
||||
|
||||
Pre-built flyer templates live in the `templates/` directory. Use the CLI to copy one with:
|
||||
|
||||
```bash
|
||||
voxvera init --template <name>
|
||||
```
|
||||
|
||||
This will create a new folder under `dist/` named `<name>-<YYYYMMDD>` containing the template files.
|
||||
|
||||
Available templates:
|
||||
|
||||
- **blank** – minimal placeholder files, also used when extracting fields from a PDF.
|
||||
- **voxvera** – example flyer showcasing the VoxVera project.
|
||||
@@ -1,75 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
This page collects common issues encountered when hosting or accessing flyers.
|
||||
|
||||
## Tor connectivity
|
||||
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||
|
||||
## Supported deployment target
|
||||
- The supported persistent-host setup is Linux with `systemd --user`.
|
||||
- Windows, macOS, Docker, Flatpak, AppImage, Homebrew, and Chocolatey are currently experimental and may not recover hosting automatically after reboot or network interruptions.
|
||||
|
||||
## Tor port detection
|
||||
|
||||
`voxvera serve` auto-detects Tor by probing common ports (9050/9150 for SOCKS, 9051/9151 for control). If detection fails -- for example when Tor runs on non-standard ports -- you can override with environment variables:
|
||||
|
||||
```bash
|
||||
TOR_SOCKS_PORT=19050 TOR_CONTROL_PORT=19051 voxvera serve
|
||||
```
|
||||
|
||||
If no running Tor is found, the defaults (9050/9051) are used and OnionShare will attempt to connect on those ports.
|
||||
|
||||
## Firewall rules
|
||||
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||
|
||||
## SELinux
|
||||
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||
|
||||
## OnionShare crashes
|
||||
If `voxvera serve` prints "OnionShare exited unexpectedly", check the log file
|
||||
`host/<folder_name>/onionshare.log` for details. Common causes:
|
||||
|
||||
- Tor is not running (`sudo systemctl start tor`)
|
||||
- A port conflict with another service
|
||||
- Missing `onionshare-cli` (run `voxvera check`)
|
||||
|
||||
## Onion URL changed unexpectedly
|
||||
The onion URL is tied to the Ed25519 keypair stored in
|
||||
`host/<folder_name>/.onionshare-session`. If this file is deleted, a new
|
||||
keypair (and URL) will be generated on the next `voxvera serve`. The
|
||||
`voxvera import` command preserves this file automatically, but manual
|
||||
deletion of the `host/` directory will destroy it.
|
||||
|
||||
## Hosting does not return after reboot or network loss
|
||||
On Linux, install or verify the recovery timer:
|
||||
|
||||
```bash
|
||||
voxvera autostart
|
||||
systemctl --user status voxvera-start.timer
|
||||
systemctl --user status voxvera-start.service
|
||||
```
|
||||
|
||||
The supported recovery path is the recurring `systemd --user` timer, which reruns `voxvera start-all` every few minutes.
|
||||
|
||||
## QR codes not generated
|
||||
If `voxvera build` reports "No URLs configured yet", this is expected before the first `voxvera serve`. QR codes for tear-off links are generated automatically once the .onion address is known. QR codes for the content link are generated if you provided a URL during `voxvera init`.
|
||||
|
||||
## Electron GUI
|
||||
If `npm start` fails with `spawn voxvera ENOENT`, the `voxvera` command is not in your `PATH`. Install it with `pipx install git+https://github.com/PR0M3TH3AN/VoxVera.git` or run `./install.sh` from the repository.
|
||||
|
||||
## Missing dependencies
|
||||
Run `voxvera check` to verify your setup. The command checks for required
|
||||
Python packages (`qrcode`, `Pillow`, `jsmin`, `htmlmin`, `pypdf`) and
|
||||
external tools (`onionshare-cli`), then prints a summary of anything
|
||||
missing. To install everything:
|
||||
|
||||
```bash
|
||||
# Recommended: use the install script (handles Tor + OnionShare too)
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
|
||||
# Or reinstall just the Python package
|
||||
pipx install --force 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
```
|
||||
@@ -1,130 +0,0 @@
|
||||
# Maelezo ya Matumizi
|
||||
|
||||
Mwongozo huu unashughulikia taratibu za kawaida za CLI. Angalia `docs/docker.md` kwa maelekezo ya Docker na `docs/templates.md` kwa violezo vya vipeperushi vinavyopatikana.
|
||||
|
||||
## Mahitaji ya Awali
|
||||
|
||||
VoxVera imeundwa kuwa rahisi kubebeka na inahitaji vitegemezi vichache vya mfumo.
|
||||
|
||||
### 1. Programu Zinazojitegemea (Zinazopendekezwa)
|
||||
Unaweza kupakua programu zinazojitegemea na zisizo na vitegemezi kwa mfumo wako wa uendeshaji:
|
||||
- **Linux:** `voxvera-linux`
|
||||
- **Windows:** `voxvera-windows.exe`
|
||||
- **macOS:** `voxvera-macos`
|
||||
|
||||
Programu hizi zinajumuisha kila kitu kinachohitajika ili kuendesha VoxVera (isipokuwa `onionshare-cli`).
|
||||
|
||||
### 2. Kisakinishi cha Mstari Mmoja
|
||||
Vinginevyo, sakinisha kupitia hati yetu ya kiotomatiki:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/PR0M3TH3AN/VoxVera/main/install.sh | bash
|
||||
```
|
||||
|
||||
### 3. Usakinishaji wa Mwongozo wa Python
|
||||
Ikiwa unapendelea kuendesha kutoka kwenye chanzo:
|
||||
|
||||
```bash
|
||||
pipx install 'voxvera@git+https://github.com/PR0M3TH3AN/VoxVera.git@main'
|
||||
sudo apt install tor onionshare-cli # Debian/Ubuntu
|
||||
```
|
||||
|
||||
## Hatua kwa Hatua
|
||||
|
||||
1. **Anzisha:** Endesha `voxvera init` na ufuate maelekezo. Utaulizwa kuchagua lugha yako kwanza.
|
||||
2. **Jenga:** Tengeneza rasilimali za kipeperushi. Kila ujenzi huunda kiotomatiki faili ya `voxvera-portable.zip` kwenye folda ya kipeperushi, ikiruhusu wengine kupakua zana nzima moja kwa moja kutoka kwenye kipeperushi chako.
|
||||
```bash
|
||||
voxvera build
|
||||
```
|
||||
3. **Tumia:** Chapisha kipeperushi kupitia Tor:
|
||||
```bash
|
||||
voxvera serve
|
||||
```
|
||||
Hii hutambua kiotomatiki mfumo wako wa Tor, inaanzisha OnionShare, na kuandika anwani ya .onion iliyozalishwa kwenye viungo vya kipeperushi.
|
||||
|
||||
## Usaidizi wa Lugha
|
||||
|
||||
VoxVera imetafsiriwa kikamilifu. Unaweza kubadilisha upendeleo wako wa lugha kwa kudumu ukitumia kiteuzi shirikishi au njia ya mkato ya moja kwa moja:
|
||||
|
||||
- **Kiteuzi Shirikishi:** `voxvera lang`
|
||||
- **Njia ya Mkato ya Moja kwa Moja:** `voxvera --lang sw` (inaweka upendeleo kuwa Kiswahili)
|
||||
|
||||
### Lugha Zinazotumika:
|
||||
- **Kiingereza:** `en`
|
||||
- **Kihispania:** `es` (jina mbadala: `--idioma`)
|
||||
- **Kijerumani:** `de` (jina mbadala: `--sprache`)
|
||||
- **Kiswahili:** `sw`
|
||||
|
||||
Unaweza pia kulazimisha lugha maalum kwa amri moja bila kubadilisha upendeleo wako wa kudumu:
|
||||
- **Kiingereza:** `voxvera --lang en check`
|
||||
- **Kiswahili:** `voxvera --lang sw check`
|
||||
|
||||
Vipeperushi vilivyozalishwa hutambua kiotomatiki lugha ya kivinjari cha mgeni na kubadilisha maandishi ya UI ipasavyo.
|
||||
|
||||
## Usimamizi wa Seva
|
||||
|
||||
Simamia vipeperushi vingi na utambulisho wao wa Tor kutoka kwenye menyu moja shirikishi:
|
||||
|
||||
```bash
|
||||
voxvera manage
|
||||
```
|
||||
|
||||
Vipengele:
|
||||
- **--- Unda Tovuti/Kipeperushi Kipya ---**: Anza mchakato mzima wa usanidi.
|
||||
- **--- Anzisha Tovuti Zote ---**: Anzisha au simamisha vipeperushi vyote kwenye kundi lako kwa mpigo mmoja.
|
||||
- **Hali ya Wakati Halisi**: Angalia URL za .onion zinazofanya kazi na viashiria vya maendeleo ya kuanza kwa Tor.
|
||||
- **Udhibiti wa Kibinafsi**: Hamisha kama Zip tovuti maalum kwenye ZIP au uzifute.
|
||||
|
||||
## Uakisi wa Ulimwengu (Usambazaji wa Virusi)
|
||||
|
||||
Ili kuhakikisha VoxVera inaendelea kupatikana hata kama hifadhi kuu zitadhibitiwa, kila kipeperushi hufanya kazi kama kioo cha zana hiyo.
|
||||
|
||||
Unapohifadhi kipeperushi, kitufe cha **"Pakua Zana na Chanzo"** kwenye ukurasa wa kutua hutoa `voxvera-portable.zip` iliyo na:
|
||||
- Chanzo kamili na lugha zote zinazotumika.
|
||||
- Vitegemezi vyote vya Python (vilivyowekwa mapema).
|
||||
- Programu za Tor za mifumo mbalimbali.
|
||||
|
||||
Hii inaruhusu kila mtu anayekagua kipeperushi chako kuwa msambazaji mpya wa zana ya VoxVera.
|
||||
|
||||
## Hamisha na Hifadhi Nakala
|
||||
|
||||
Hifadhi nakala za utambulisho wako wa kipekee wa Tor (ili URL yako ya .onion isibadilike kamwe) au hamisha vipeperushi vyako kwenye mashine nyingine.
|
||||
|
||||
- **Hamisha tovuti moja**: `voxvera export <jina_la_folda>`
|
||||
- **Hamisha tovuti zote**: `voxvera export-all`
|
||||
|
||||
**Mahali pa kuhifadhi:** Hamisho zote zinahifadhiwa kwenye `~/voxvera-exports/` kwenye mifumo yote.
|
||||
|
||||
## Ingiza na Rejesha
|
||||
|
||||
Rejesha usanidi wako wote kwenye mashine mpya kwa kuhamisha faili zako za ZIP kwenda `~/voxvera-exports/` na uendeshe:
|
||||
|
||||
```bash
|
||||
voxvera import-multiple
|
||||
```
|
||||
|
||||
## Uwezo wa Kubebeka na Matumizi ya Nje ya Mtandao
|
||||
|
||||
Ikiwa unahitaji kuendesha VoxVera kwenye mashine isiyo na ufikiaji wa mtandao, unaweza kupakua vitegemezi kwanza:
|
||||
|
||||
```bash
|
||||
voxvera vendorize
|
||||
```
|
||||
|
||||
Hii inapakua maktaba zote za Python zinazohitajika kwenye `voxvera/vendor/`. Kisha zana itatoa kipaumbele kwa faili hizi za kienyeji, ikiruhusu iendeshe bila `pip install`.
|
||||
|
||||
## Ingiza kwa Wingi (JSON)
|
||||
|
||||
Ili kuzalisha vipeperushi kwa wingi kutoka kwa faili nyingi za usanidi wa JSON, ziweke kwenye folda ya `imports/` na uendeshe:
|
||||
|
||||
```bash
|
||||
voxvera batch-import
|
||||
```
|
||||
|
||||
## Jinsi URL Zinavyofanya Kazi
|
||||
|
||||
Kila kipeperushi kina URL mbili tofauti:
|
||||
- **Kiungo cha kutolewa** (kinachozalishwa kiotomatiki): Anwani ya .onion ambapo kipeperushi kinahifadhiwa.
|
||||
- **Kiungo cha maudhui** (kilichosanidiwa na mtumiaji): URL ya nje inayoelekeza kwenye tovuti, video, au upakuaji.
|
||||
|
||||
Huna haja ya kuingiza anwani ya .onion kwa mikono; VoxVera inashughulikia hili kiotomatiki wakati wa awamu ya `serve`.
|
||||
Vendored
-42
@@ -1,42 +0,0 @@
|
||||
# AI Agent Instructions for VoxVera
|
||||
|
||||
This guide is for AI agents (like Gemini, Claude, or GPT) contributing to the VoxVera project. Follow these protocols to maintain the architectural integrity and multi-language support.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
1. **Security-First**: VoxVera is a Tor-based tool. Never suggest features that leak IP addresses or use non-Tor external resources (CDNs, etc.).
|
||||
2. **Local-First**: All assets (fonts, dependencies, binaries) must be self-contained within the `voxvera/` package to support the Universal Mirroring model.
|
||||
3. **Tokenized UI**: Never hardcode user-facing strings. Always add them to `voxvera/locales/en.json` and use the `t('cli.token')` helper.
|
||||
4. **Markdown Redaction**: Use `~~text~~` in locale JSONs for strike-through effects. Both the build system and the JS engine handle the conversion to `<span class="redacted">` automatically.
|
||||
5. **Visual Width Testing**: When modifying UI or adding languages, verify that long or complex strings (e.g., Hindi ligatures or CJK characters) do not exceed the visual unit limits defined in the CLI.
|
||||
|
||||
## Localization Protocol
|
||||
|
||||
When adding a new language or updating an existing one:
|
||||
- **CLI/Flyers**: Update `voxvera/locales/{lang}.json`. Include `meta`, `cli`, `web`, and `landing` categories.
|
||||
- **Landing Page**:
|
||||
- Directly update the `const locales` object in `site/index.html`.
|
||||
- **Crucial**: Run `voxvera build-site` to generate the latest portable bundle and refresh the pre-rendered HTML.
|
||||
- **Documentation**:
|
||||
- Master templates live in `docs/templates/`.
|
||||
- Localized overrides live in `voxvera/locales/{lang}/docs/`.
|
||||
- **Crucial**: After any change to locales or templates, you MUST run `voxvera build-docs` to synchronize the output in `docs/{en,es,de}/`.
|
||||
|
||||
## Universal Mirroring
|
||||
|
||||
VoxVera propagates through its own flyers.
|
||||
- Every `voxvera build` and `voxvera build-site` generates `voxvera-portable.zip`.
|
||||
- If you modify the core source code, ensure the `bundle_portable` function in `voxvera/cli.py` still correctly captures all necessary directories (especially `vendor/`, `locales/`, and `resources/`).
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before finishing a task, ensure you have:
|
||||
1. Run unit tests: `pytest tests/test_cli.py`.
|
||||
2. Verified the localization: `voxvera --lang {lang} check`.
|
||||
3. Rebuilt the documentation: `voxvera build-docs`.
|
||||
4. Synchronized the public site: `voxvera build-site`.
|
||||
5. Verified the portable bundle exists: `ls -l voxvera/host/*/download/voxvera-portable.zip` and `ls -l site/download/voxvera-portable.zip`.
|
||||
|
||||
---
|
||||
|
||||
Follow these rules to ensure VoxVera remains a robust, viral, and decentralized tool for truth.
|
||||
Vendored
-47
@@ -1,47 +0,0 @@
|
||||
# Contributing to VoxVera
|
||||
|
||||
Thank you for your interest in contributing to VoxVera! This project aims to be a global, censorship-resistant tool, and your help—especially with translations—is vital.
|
||||
|
||||
## Adding a New Language
|
||||
|
||||
VoxVera uses a centralized token system for the CLI and Web components, and a template-based system for Documentation. To add a new language (e.g., French/`fr`), follow this checklist:
|
||||
|
||||
### 1. The Token File
|
||||
Create a new JSON file in `voxvera/locales/{lang_code}.json`.
|
||||
- Use `en.json` as your master template.
|
||||
- **`meta`**: Include the native language name and a flag emoji.
|
||||
- **`cli`**: Translate all strings used in the terminal interface.
|
||||
- **`web`**: Translate strings used on the generated landing pages and flyers.
|
||||
- **`landing`**: Translate the specific content for the official VoxVera website.
|
||||
- **Formatting**: You can use Markdown-style strike-throughs (`~~redacted text~~`) in any of these strings; they will be automatically converted to the stylized "redacted" effect on the flyers.
|
||||
|
||||
### 2. The Landing Page
|
||||
The main landing page is generated from the shared template and locale files.
|
||||
- Add your language in `voxvera/locales/{lang_code}.json`.
|
||||
- Do **not** edit `site/index.html` directly; it is generated output.
|
||||
- Run `voxvera build-site` to refresh the public assets and inject your new locale into the generated HTML.
|
||||
|
||||
### 3. Documentation
|
||||
VoxVera uses the **Doc-Sync Engine** to keep manuals in sync.
|
||||
- Create localized Markdown files in `voxvera/locales/{lang_code}/docs/`.
|
||||
- Use the templates in `docs/templates/` as your guide.
|
||||
- You can use `{{t('cli.token_name')}}` to reference terminal commands automatically.
|
||||
|
||||
### 4. Build and Verify
|
||||
Run the following commands to verify your changes:
|
||||
- `voxvera --lang {lang_code} check` (Verify CLI translation)
|
||||
- `voxvera build-docs` (Generate localized manuals)
|
||||
- `voxvera build-site` (Synchronize the public website and generate the latest portable bundle)
|
||||
- Open the generated `site/index.html` in a browser and test the language switcher.
|
||||
|
||||
## Code Contributions
|
||||
- **Dependencies**: if you add a new Python library to `requirements.txt`, you MUST run `voxvera vendorize` to include it in the portable distribution.
|
||||
- **Layout Integrity**: VoxVera uses visual width validation. If you add new UI elements, ensure they respect the physical boundaries of an 8.5"x11" flyer.
|
||||
- **Tests**: Ensure all tests pass: `pytest tests/`. Run the integrity suite specifically when modifying locales: `pytest tests/test_integrity.py`.
|
||||
- **Generated artifacts**: Treat `voxvera/resources/bin/` as local build output, not source files. Release binaries belong in GitHub Releases, not hand-edited repo state.
|
||||
- **Style**: Follow the existing coding style (PEP 8 for Python).
|
||||
- **Documentation**: If adding a new feature, update the master templates in `docs/templates/` and run `voxvera build-docs`.
|
||||
|
||||
---
|
||||
|
||||
Together, we can ensure that truth remains accessible to everyone, everywhere.
|
||||
Vendored
-19
@@ -1,19 +0,0 @@
|
||||
# Docker Usage
|
||||
|
||||
Experimental: the container path is not yet a production-grade hidden-service deployment target. Linux with `systemd --user` remains the supported persistent-host environment.
|
||||
|
||||
A prebuilt image containing Tor, OnionShare and the `voxvera` CLI is published to
|
||||
`ghcr.io/voxvera/voxvera`.
|
||||
|
||||
```bash
|
||||
# pull the image
|
||||
docker pull ghcr.io/voxvera/voxvera:latest
|
||||
|
||||
# run the experimental container with flyers stored in ./flyers
|
||||
mkdir -p flyers
|
||||
docker run -it --rm -v "$(pwd)/flyers:/flyers" ghcr.io/voxvera/voxvera
|
||||
```
|
||||
|
||||
The container stores runtime state under `/flyers`, seeds a default `config.json` if needed, and retries `voxvera start-all` periodically after the initial `quickstart`.
|
||||
|
||||
Use this path for testing only until the container runtime and background recovery behavior are validated end-to-end.
|
||||
Loaded 100 of 3045 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user