Commit Graph

13 Commits

Author SHA1 Message Date
Aaron D. Lee
88f5571bf9 Complete rebrand cleanup: remaining env vars and references
Fix STEGASOO_* env vars → FIELDWITNESS_* and VERISOO_* → FIELDWITNESS_*
across stego module, attest module, and frontends. Wire format
identifiers (VERISOO\x00 magic bytes, STEGASOO-Z: QR prefixes)
intentionally preserved for backwards compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:07:31 -04:00
Aaron D. Lee
490f9d4a1d Rebrand SooSeF to FieldWitness
Complete project rebrand for better positioning in the press freedom
and digital security space. FieldWitness communicates both field
deployment and evidence testimony — appropriate for the target audience
of journalists, NGOs, and human rights organizations.

Rename mapping:
- soosef → fieldwitness (package, CLI, all imports)
- soosef.stegasoo → fieldwitness.stego
- soosef.verisoo → fieldwitness.attest
- ~/.soosef/ → ~/.fwmetadata/ (innocuous data dir name)
- SOOSEF_DATA_DIR → FIELDWITNESS_DATA_DIR
- SoosefConfig → FieldWitnessConfig
- SoosefError → FieldWitnessError

Also includes:
- License switch from MIT to GPL-3.0
- C2PA bridge module (Phase 0-2 MVP): cert.py, export.py, vendor_assertions.py
- README repositioned to lead with provenance/federation, stego backgrounded
- Threat model skeleton at docs/security/threat-model.md
- Planning docs: docs/planning/c2pa-integration.md, docs/planning/gtm-feasibility.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 15:05:13 -04:00
Aaron D. Lee
2a6900abed Implement live gossip federation server (5 phases)
Some checks failed
CI / lint (push) Failing after 1m3s
CI / typecheck (push) Failing after 32s
Phase 1: RFC 6962 consistency proofs in merkle.py
- Implemented _build_consistency_proof() with recursive subtree
  decomposition algorithm following RFC 6962 Section 2.1.2
- Added _subproof() recursive helper and _compute_root_of()
- Added standalone verify_consistency_proof() function

Phase 2: Federation API endpoints on FastAPI server
- GET /federation/status — merkle root + log size for gossip probes
- GET /federation/records?start=N&count=M — record fetch (cap 100)
- GET /federation/consistency-proof?old_size=N — Merkle proof
- POST /federation/records — accept records with trust filtering
  and SHA-256 deduplication
- Cached storage singleton for concurrent safety
- Added FEDERATION_DIR to paths.py

Phase 3: HttpTransport implementation
- Replaced stub with real aiohttp client (lazy import for optional dep)
- Reusable ClientSession with configurable timeout
- All 4 PeerTransport methods: get_status, get_records,
  get_consistency_proof, push_records
- FederationError wrapping for all network failures
- Added record_filter callback to GossipNode for trust-store filtering

Phase 4: Peer persistence (SQLite)
- New peer_store.py: SQLite-backed peer database + sync history
- Tables: peers (url, fingerprint, health, last_seen) and
  sync_history (timestamp, records_received, success/error)
- PeerStore follows dropbox.py SQLite pattern

Phase 5: CLI commands + Web UI dashboard
- CLI: federation status, peer-add, peer-remove, peer-list,
  sync-now (asyncio), history
- Flask blueprint at /federation/ with peer table, sync history,
  add/remove peer forms, local node info cards
- CSRF tokens on all forms

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 22:20:53 -04:00
Aaron D. Lee
9431033c72 Implement 7 real-world scenario features (Round 4)
Some checks failed
CI / lint (push) Failing after 52s
CI / typecheck (push) Failing after 30s
1. Source drop box: token-gated anonymous upload with auto-attestation,
   EXIF stripping, receipt codes, and self-destructing URLs. New
   /dropbox blueprint with admin panel for token management. CSRF
   exempted for source-facing upload routes.

2. Investigation namespaces: attestation records tagged with
   investigation label via metadata. Log view filters by investigation
   with dropdown. Supports long-running multi-story workflows.

3. Scale fixes: replaced O(n) full-scan perceptual hash search with
   LMDB find_similar_images() index lookup. Added incremental chain
   verification (verify_incremental) with last_verified_index
   checkpoint in ChainState.

4. Deep forensic purge: killswitch now scrubs __pycache__, pip
   dist-info, pip cache, and shell history entries containing 'soosef'.
   Runs before package uninstall for maximum trace removal.

5. Cross-org federation: new federation/exchange.py with
   export_attestation_bundle() and import_attestation_bundle().
   Bundles are self-authenticating JSON with investigation filter.
   Import validates against trust store fingerprints.

6. Wrong-key diagnostics: enhanced decrypt error messages include
   current channel key fingerprint hint. New carrier_tracker.py
   tracks carrier SHA-256 hashes and warns on reuse (statistical
   analysis risk).

7. Selective disclosure: ChainStore.selective_disclosure() produces
   proof bundles with full selected records + hash-only redacted
   records + complete hash chain for linkage verification. New
   `soosef chain disclose -i 0,5,10 -o proof.json` CLI command
   for court-ordered evidence production.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:41:41 -04:00
Aaron D. Lee
0d8c94bf82 Fix 6 security issues from post-FR audit
- Fix 3 missing CSRF tokens on admin user delete/reset and account
  key delete forms (were broken — CSRFProtect rejected submissions)
- Fix trust store path traversal: untrust_key() now validates
  fingerprint format ([0-9a-f]{32}) and checks resolved path
- Fix chain key rotation: old key is now revoked after rotation
  record, preventing compromised old keys from appending records
- Fix SSRF in deadman webhook: block private/internal IP targets
- Fix logout CSRF: /logout is now POST-only with CSRF token,
  preventing cross-site forced logout via img tags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:44:15 -04:00
Aaron D. Lee
fb0cc3e39d Implement 14 power-user feature requests for field deployment
Critical:
- FR-01: Chain verification now supports key rotation via signed rotation
  records (soosef/key-rotation-v1 content type). Old single-signer
  invariant replaced with authorized-signers set.
- FR-02: Carrier images stripped of EXIF metadata by default before
  steganographic encoding (strip_metadata=True). Prevents source
  location/device leakage.

High priority:
- FR-03: Session timeout (default 15min) + secure cookie flags
  (HttpOnly, SameSite=Strict, Secure when HTTPS)
- FR-04: CSRF protection via Flask-WTF on all POST forms. Killswitch
  now requires password re-authentication.
- FR-05: Collaborator trust store — trust_key(), get_trusted_keys(),
  resolve_attestor_name(), untrust_key() in KeystoreManager.
- FR-06: Production WSGI server (Waitress) by default, Flask dev
  server only with --debug flag.
- FR-07: Dead man's switch sends warning during grace period via
  local file + optional webhook before auto-purge.

Medium:
- FR-08: Geofence get_current_location() via gpsd for --here support.
- FR-09: Batch attestation endpoint (/attest/batch) with SHA-256
  dedup and per-file status reporting.
- FR-10: Key backup tracking with last_backup_info() and
  is_backup_overdue() + backup_reminder_days config.
- FR-11: Verification receipts signed with instance Ed25519 key
  (schema_version bumped to 2).
- FR-12: Login rate limiting with configurable lockout (5 attempts,
  15 min default).

Nice-to-have:
- FR-13: Unified `soosef status` pre-flight command showing identity,
  channel key, deadman, geofence, chain, and backup status.
- FR-14: `soosef chain export` produces ZIP with JSON manifest,
  public key, and raw chain.bin for legal discovery.

Tests: 157 passed, 1 skipped, 1 pre-existing flaky test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:35:36 -04:00
Aaron D. Lee
51c9b0a99a Fix 14 bugs and add features from power-user security audit
Critical fixes:
- Fix admin_delete_user missing current_user_id argument (TypeError on every delete)
- Fix self-signed cert OOM: bytes(2130706433) → IPv4Address("127.0.0.1")
- Add @login_required to attestation routes (attest, log); verify stays public
- Add auth guards to fieldkit (@admin_required on killswitch) and keys blueprints
- Fix cleanup_temp_files NameError in generate() route

Security hardening:
- Unify temp storage to ~/.soosef/temp/ so killswitch purge covers web uploads
- Replace Path.unlink() with secure deletion (shred fallback) in temp_storage
- Add structured audit log (audit.jsonl) for admin, key, and killswitch actions

New features:
- Dead man's switch background enforcement thread in serve + check-deadman CLI
- Key rotation: soosef keys rotate-identity/rotate-channel with archiving
- Batch attestation: soosef attest batch <dir> with progress and error handling
- Geofence CLI: set/check/clear commands with config persistence
- USB CLI: snapshot/check commands against device whitelist
- Verification receipt download (/verify/receipt JSON endpoint + UI button)
- IdentityInfo.created_at populated from sidecar meta.json (mtime fallback)

Data layer:
- ChainStore.get() now O(1) via byte-offset index built during state rebuild
- Add federation module (chain, models, serialization, entropy)

Includes 45+ new tests across chain, deadman, key rotation, killswitch, and
serialization modules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 17:06:33 -04:00
Aaron D. Lee
fb2e036e66 Fix admin route name mismatch in user_new and user_created templates
Templates referenced 'admin_user_new' (stegasoo convention) but the
soosef route is named 'admin_new_user'. Caused 500 error when clicking
"Add User" from admin panel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:53:11 -04:00
Aaron D. Lee
067c4073ee Add Verisoo attest/verify web MVP — full attestation lifecycle
Attest page (/attest):
- Image upload with optional caption and location
- EXIF auto-extraction toggle
- Creates Ed25519-signed attestation record
- Stores in verisoo append-only binary log + LMDB index
- Displays: record ID, attestor fingerprint, timestamp, image hashes

Verify page (/verify):
- Image upload for verification against local attestation log
- SHA-256 exact matching + perceptual hash matching (pHash, dHash)
- Shows match type (exact/perceptual), hash distances, attestor info
- Color-coded distance badges (green=0, info<5, warning<10, danger>=10)

Attestation log (/attest/log):
- Lists recent attestations with short ID, attestor, timestamp, SHA-256
- Shows total record count

Verified: full lifecycle works — attest image → verify same image → exact match found

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:02:49 -04:00
Aaron D. Lee
317ef0f2ae Port encode/decode/tools/about routes from stegasoo (2,083 lines)
New file stego_routes.py:
- register_stego_routes() mounts all encode/decode routes on the Flask app
- Async encode with ThreadPoolExecutor + progress polling
- Subprocess isolation for crash-safe stegasoo operations
- Image + audio encode/decode with full validation
- Encode result display with download
- Tools API routes (capacity, EXIF, rotate, compress, convert)
- About page with crypto documentation

Real templates (replacing stubs):
- encode.html (889 lines): full form with carrier upload, passphrase,
  PIN, RSA key, embed mode selection, async progress bar
- decode.html (681 lines): decode form with credential inputs
- encode_result.html (242 lines): result display with download
- about.html (602 lines): security documentation

All routes verified working with auth flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 16:52:18 -04:00
Aaron D. Lee
10838ce828 Replace stub templates with real stegasoo UI for generate, tools, admin
Generate page:
- Full form with passphrase word count slider, PIN/RSA toggles
- Credential display with copy buttons, QR code, entropy breakdown
- Channel key generation accordion
- Added QR code routes (generate_qr, generate_qr_download)
- Added RSA key download route (download_key)
- Fixed route name: encode_page → encode

Tools page:
- Image capacity checker, EXIF viewer/editor, rotation, compression
- Format conversion, image comparison
- (API routes for tools pending — UI renders but actions need backend)

Admin users page:
- User table with role badges, creation dates
- Add/delete/reset password actions
- Fixed route names to match soosef conventions
- Added user_count and current_user to template context

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 16:42:42 -04:00
Aaron D. Lee
a23a034838 Wire up auth, stego routes, and full web UI with login flow
Auth system:
- Copy auth.py from stegasoo, adapt DB path to ~/.soosef/auth/soosef.db
- Add setup/login/logout/recover/account routes
- Add admin user management routes (users, create, delete, reset)
- Full RBAC: admin_required and login_required decorators working

Stego routes (mounted directly in app.py):
- Generate credentials with QR code support
- Encode/decode/tools placeholder pages (full route migration is Phase 1b)
- Channel status API, capacity comparison API, download API

Support modules (copied verbatim from stegasoo):
- subprocess_stego.py: crash-safe subprocess isolation
- stego_worker.py: worker script for subprocess
- temp_storage.py: file-based temp storage with auto-expiry
- ssl_utils.py: self-signed cert generation

Templates and JS:
- All stegasoo templates copied to stego/ subdirectory
- Auth templates (login, setup, account, recover) at root
- Admin templates (users, settings)
- JS files: soosef.js (renamed from stegasoo.js), auth.js, generate.js

Verified: full login flow works (setup → login → authenticated routes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 15:53:58 -04:00
Aaron D. Lee
b8d4eb5933 Add core modules, web frontend, CLI, keystore, and fieldkit
Core:
- paths.py: centralized ~/.soosef/ path constants
- config.py: JSON config loader with dataclass defaults
- exceptions.py: SoosefError hierarchy
- cli.py: unified Click CLI wrapping stegasoo + verisoo + native commands

Keystore:
- manager.py: unified key management (Ed25519 identity + channel keys)
- models.py: IdentityInfo, KeystoreStatus dataclasses
- export.py: encrypted key bundle export/import for USB transfer

Fieldkit:
- killswitch.py: ordered emergency data destruction (keys first)
- deadman.py: dead man's switch with check-in timer
- tamper.py: SHA-256 file integrity baseline + checking
- usb_monitor.py: pyudev USB whitelist enforcement
- geofence.py: haversine-based GPS boundary checking

Web frontend (Flask app factory + blueprints):
- app.py: create_app() factory with context processor
- blueprints: stego, attest, fieldkit, keys, admin
- templates: base.html (dark theme, unified nav), dashboard, all section pages
- static: CSS, favicon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:30:13 -04:00