Commit Graph

10 Commits

Author SHA1 Message Date
Aaron D. Lee
0312204340 Fix e2e test infrastructure and app bugs found by Playwright
Some checks failed
CI / lint (push) Failing after 13s
CI / typecheck (push) Failing after 11s
Fixes:
- Add frontends/web/ to sys.path in e2e conftest for temp_storage import
- Fix .fieldwitness → .fwmetadata in e2e conftest
- Fix NameError in /health endpoint (auth_is_authenticated → is_authenticated)
- Fix NameError in /login POST (config → app.config["FIELDWITNESS_CONFIG"])
- Add session-scoped admin_user fixture for reliable test ordering
- Fix navigation test assertions (health fetch URL, title checks, logout)
- Increase server startup timeout and use /login for health polling

Status: 17/39 e2e tests passing (auth + navigation). Remaining failures
are selector/assertion mismatches needing template-specific tuning.
350 unit/integration tests continue passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 19:58:34 -04:00
Aaron D. Lee
16318daea3 Add comprehensive test suite: integration tests + Playwright e2e
Some checks failed
CI / lint (push) Failing after 12s
CI / typecheck (push) Failing after 12s
Integration tests (350 passing):
- test_evidence_summary.py: HTML/PDF generation, XSS safety, anchor rendering
- test_tor.py: Tor module unit tests (mocked, no Tor needed)
- test_c2pa_importer.py: Import result dataclass, trust evaluation, graceful degradation
- test_file_attestation.py: All file types (PNG, PDF, CSV, empty, large), determinism
- test_paths.py: Registry correctness, env var override, all paths under BASE_DIR
- test_killswitch_coverage.py: Tor keys, trusted keys, carrier history destruction

Playwright e2e infrastructure:
- tests/e2e/ with conftest (live server, auth fixtures), helpers (test file generators)
- test_auth.py: Setup flow, login/logout, protected routes
- test_attest.py: Image/PDF/CSV attestation, verify, attestation log
- test_dropbox.py: Token creation, source upload, branding check
- test_keys.py: Identity display, trust store
- test_fieldkit.py: Status dashboard, killswitch page
- test_navigation.py: All nav links, responsive layout

Run: pytest (unit/integration) or pytest -m e2e tests/e2e/ (browser)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:22:12 -04:00
Aaron D. Lee
5b0d90eeaf Fix all power-user review issues (FR-01 through FR-12)
Some checks failed
CI / lint (push) Failing after 12s
CI / typecheck (push) Failing after 12s
FR-01: Fix data directory default from ~/.fieldwitness to ~/.fwmetadata
FR-02/05/07: Accept all file types for attestation (not just images)
  - Web UI, CLI, and batch now accept PDFs, CSVs, audio, video, etc.
  - Perceptual hashing for images, SHA-256-only for everything else
FR-03: Implement C2PA import path + CLI commands (export/verify/import/show)
FR-04: Fix GPS downsampling bias (math.floor → round)
FR-06: Add HTML/PDF evidence summaries for lawyers
  - Always generates summary.html, optional summary.pdf via xhtml2pdf
FR-08: Fix CLI help text ("FieldWitness -- FieldWitness" artifact)
FR-09: Centralize stray paths (trusted_keys, carrier_history, last_backup)
FR-10: Add 67 C2PA bridge tests (vendor assertions, cert, GPS, export)
FR-12: Add Tor onion service support for source drop box
  - fieldwitness serve --tor flag, persistent/transient modes
  - Killswitch covers hidden service keys

Also: bonus fix for attest/api.py hardcoded path bypassing paths.py

224 tests passing (67 new).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:10:37 -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
fef552b9c1 Fix 3 architectural bottlenecks blocking cross-domain adoption
Some checks failed
CI / lint (push) Failing after 58s
CI / typecheck (push) Failing after 32s
Bottleneck 1: ImageHashes generalization
- phash and dhash now default to "" (optional), enabling attestation
  of CSV datasets, sensor logs, documents, and any non-image file
- Added ImageHashes.from_file() for arbitrary file attestation
  (SHA-256 only, no perceptual hashes)
- Added ImageHashes.is_image property to check if perceptual matching
  is meaningful
- Added content_type field to AttestationRecord ("image", "document",
  "data", "audio", "video") — backward compatible, defaults to "image"
- from_dict() now tolerates missing phash/dhash fields

Bottleneck 2: Lazy path resolution
- Converted 5 modules from eager top-level path imports to lazy
  access via `import soosef.paths as _paths`:
  config.py, deadman.py, usb_monitor.py, tamper.py, anchors.py
- Paths now resolve at use-time, not import-time, so --data-dir
  and SOOSEF_DATA_DIR overrides propagate correctly to all modules
- Enables portable mode (run entirely from USB stick)
- Updated deadman enforcement tests for new path access pattern

Bottleneck 3: Delivery acknowledgment chain records
- New CONTENT_TYPE_DELIVERY_ACK = "soosef/delivery-ack-v1"
- ChainStore.append_delivery_ack() records bundle receipt with
  sender fingerprint and record count
- import_attestation_bundle() auto-generates ack when chain store
  and private key are provided
- Enables two-way federation handshakes (art provenance, legal
  chain of custody, multi-org evidence exchange)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:27: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
e3bc1cce1f Consolidate stegasoo and verisoo into soosef monorepo
Merge stegasoo (v4.3.0, steganography) and verisoo (v0.1.0, attestation)
as subpackages under soosef.stegasoo and soosef.verisoo. This eliminates
cross-repo coordination and enables atomic changes across the full stack.

- Copy stegasoo (34 modules) and verisoo (15 modules) into src/soosef/
- Convert all verisoo absolute imports to relative imports
- Rewire ~50 import sites across soosef code (cli, web, keystore, tests)
- Replace stegasoo/verisoo pip deps with inlined code + pip extras
  (stego-dct, stego-audio, attest, web, api, cli, fieldkit, all, dev)
- Add _availability.py for runtime feature detection
- Add unified FastAPI mount point at soosef.api
- Copy and adapt tests from both repos (155 pass, 1 skip)
- Drop standalone CLI/web frontends; keep FastAPI as optional modules
- Both source repos tagged pre-monorepo-consolidation on GitHub

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:06:14 -04:00
Aaron D. Lee
17147856d1 Fix all 98 ruff lint errors across codebase
Some checks failed
CI / lint (push) Successful in 46s
CI / typecheck (push) Failing after 22s
CI / test (push) Failing after 20s
- Remove unused imports (app.py, stego_routes.py, killswitch.py, etc.)
- Sort import blocks (I001)
- Add missing os import in stego_routes.py (F821)
- Rename shadowed Click commands to avoid F811 (status→chain_status, show→chain_show)
- Rename uppercase locals R→earth_r, _HAS_QRCODE_READ→_has_qrcode_read (N806)
- Suppress false-positive F821 for get_username (closure scope)
- Use datetime.UTC alias (UP017)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:30:01 -04:00
Aaron D. Lee
5c74a5f4aa Fix black formatting and target Python 3.12 in CI
Some checks failed
CI / lint (push) Failing after 36s
CI / typecheck (push) Failing after 37s
CI / test (push) Failing after 24s
Reformat 8 files and add --target-version py312 to avoid
3.13 AST parsing issues with Python 3.12 container.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:26:32 -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