guardianproject/haven
Haven is for people who need a way to protect their personal spaces and possessions without compromising their own privacy, through an Android app and on-device sensors
Stale — last commit 4y ago
weakest axiscopyleft license (GPL-3.0) — review compatibility; last commit was 4y ago…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓30+ active contributors
- ✓Distributed ownership (top contributor 20% of recent commits)
- ✓GPL-3.0 licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ⚠Stale — last commit 4y ago
- ⚠GPL-3.0 is copyleft — check downstream compatibility
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/guardianproject/haven)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/guardianproject/haven on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: guardianproject/haven
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/guardianproject/haven shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 4y ago
- 30+ active contributors
- Distributed ownership (top contributor 20% of recent commits)
- GPL-3.0 licensed
- CI configured
- ⚠ Stale — last commit 4y ago
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live guardianproject/haven
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/guardianproject/haven.
What it runs against: a local clone of guardianproject/haven — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in guardianproject/haven | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 1320 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of guardianproject/haven. If you don't
# have one yet, run these first:
#
# git clone https://github.com/guardianproject/haven.git
# cd haven
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of guardianproject/haven and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "guardianproject/haven(\\.git)?\\b" \\
&& ok "origin remote is guardianproject/haven" \\
|| miss "origin remote is not guardianproject/haven (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "build.gradle" \\
&& ok "build.gradle" \\
|| miss "missing critical file: build.gradle"
test -f "README.md" \\
&& ok "README.md" \\
|| miss "missing critical file: README.md"
test -f ".gitmodules" \\
&& ok ".gitmodules" \\
|| miss "missing critical file: .gitmodules"
test -f "CHANGELOG" \\
&& ok "CHANGELOG" \\
|| miss "missing critical file: CHANGELOG"
test -f "LICENSE" \\
&& ok "LICENSE" \\
|| miss "missing critical file: LICENSE"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1320 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1290d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/guardianproject/haven"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Haven is an Android app that turns a smartphone into a physical security sensor network, using on-device accelerometers, microphones, light sensors, and motion detectors to monitor spaces for intrusion. It securely reports alerts via Signal and Tor, designed for investigative journalists and human rights defenders to detect unwanted physical access without compromising digital privacy. Single Android application module (not monorepo) with build.gradle at root driving compilation. Java dominates (255KB) with growing Kotlin (36KB), suggesting gradual migration. Real files suggest Activities/Services in Java mixed with Kotlin components; sensor integrations and messaging (Signal/Tor) likely in separate packages under src/main/java/org/havenapp/.
👥Who it's for
Investigative journalists, human rights defenders, and people at risk of forced disappearance who need to detect unauthorized physical access to their spaces; also security-conscious individuals wanting a privacy-first alternative to traditional home monitoring systems.
🌱Maturity & risk
Actively developed with public beta status (v2001+); uses Travis CI for builds and has structured Android Gradle setup with compileSdkVersion 30. The codebase shows professional organization (255KB Java, 36KB Kotlin) and security-focused dependencies (Signal, Tor integration). Appears production-ready but ongoing refinement evident from mixed Java/Kotlin migration.
Primary risks: single organization (Guardian Project/FPF) maintains core; Kotlin/Java interop complexity during migration; relies on external cryptographic libraries (Signal, Tor) whose vulnerabilities cascade; no visible test suite in file list suggests coverage gaps. Last Gradle config dates to 2021 (Kotlin 1.5.21, Gradle 4.2.2) which are now outdated; dependency on Android SDK 30 (released 2020) indicates maintenance lag.
Active areas of work
Transitioning from pure Java to Kotlin (kotlin-android and kotlin-kapt plugins active); using View Binding (buildFeatures.viewBinding true) for modern UI patterns. No recent commit data visible, but Gradle setup indicates attempts to stay current with Android tooling (SDK 30, buildTools 30.0.3). Translations via Weblate (.tx/config) suggest active localization work.
🚀Get running
git clone https://github.com/guardianproject/haven.git
cd haven
# Requires Android Studio with SDK 30+ and Java 11+
# Build via Gradle wrapper (if present) or: gradle assemble
# Or import into Android Studio and build via IDE
Daily commands:
No traditional 'dev server' (Android app). In Android Studio: Open project → Sync Gradle → Run on emulator/device. Or: ./gradlew assemble to build APK (wrapper presence unknown; fallback: gradle assemble).
🗺️Map of the codebase
build.gradle— Root build configuration defining Kotlin/Android SDK versions, Gradle plugins, and version extraction from Git tags—all builds depend on this setup.README.md— Project mission statement and feature overview; required reading to understand Haven's purpose as a privacy-respecting sensor-monitoring app..gitmodules— Defines external dependencies and submodules integrated into the codebase; critical for reproducible builds.CHANGELOG— Release history and breaking changes; essential for understanding evolution of features and APIs.LICENSE— GNU GPL or similar open-source license; establishes legal terms for contribution and distribution.code-of-conduct.md— Community guidelines for contributors; sets expectations for respectful collaboration..travis.yml— CI/CD pipeline configuration; defines how code is tested and built on every commit.
🧩Components & responsibilities
- MonitoringService (Android Service, Sensor Manager API) — Lifecycle manager for all sensor listeners; coordinates event aggregation and cooldown logic.
- Failure mode: If service crashes, all monitoring halts; user may not notice and believes app is still armed.
- Sensor Array (Motion, Sound, Light, Vibration) (Android SensorManager, audio focus API) — Acquires raw sensor values and evaluates threshold conditions; generates event objects.
- Failure mode: Sensor malfunction or permission revocation silently disables that modality; multimodal fallback helps but may reduce detection capability.
- AlertManager (Signal Protocol, Tor Android, local logging) — Logs events, applies rate limiting, encrypts payloads, and routes to configured transport (Signal/Tor).
- Failure mode: Transport unavailability causes alert queuing; old alerts may be lost if device reboots or storage fills.
- Settings/Preferences (Android SharedPreferences, PreferenceActivity) — UI for configuring sensor thresholds, transport endpoint, recipient identifiers, and monitoring intervals.
- Failure mode: Misconfiguration (e.g., invalid threshold) may cause false positives or missed detection.
🔀Data flow
Device Sensors→MonitoringService— Raw accelerometer, microphone amplitude, light level, proximity data streamed via SensorManager callbacks.MonitoringService→AlertManager— Threshold breach events (with timestamp, sensor type, value) passed when breach detected.AlertManager→Signal/Tor Transport— Event payload encrypted and serialized (JSON or protobuf) for transmission.Transport→Recipient (Journalist/Defender)— Encrypted alert delivered via Signal chat, Tor hidden service endpoint, or configured webhook.User Settings→MonitoringService & AlertManager— Threshold values, transport credentials, and monitoring intervals read from SharedPreferences on app start and when settings changed.
🛠️How to make changes
Add a New Sensor Monitor
- Create sensor handler class in app source following existing sensor patterns (motion, sound, vibration, light) (
app/src/main/java/org/guardianproject/haven/[SensorType]Monitor.kt) - Register sensor in main monitoring service that coordinates all sensor listeners (
app/src/main/java/org/guardianproject/haven/MonitoringService.kt) - Add sensor configuration options to settings/preferences UI (
app/src/main/java/org/guardianproject/haven/SettingsActivity.kt) - Integrate sensor events into alert/logging system for secure signal/Tor transmission (
app/src/main/java/org/guardianproject/haven/AlertManager.kt)
Add Support for a New Encryption/Communication Channel
- Implement transport abstraction (Signal, Tor, WebHook, etc.) in communication module (
app/src/main/java/org/guardianproject/haven/transport/TransportProvider.kt) - Add configuration UI fields for transport credentials/endpoints (
app/src/main/java/org/guardianproject/haven/SettingsActivity.kt) - Register transport in AlertManager so sensor events route through new channel (
app/src/main/java/org/guardianproject/haven/AlertManager.kt) - Update build.gradle with any new encryption libraries (Signal, Tor libraries, etc.) (
build.gradle)
Add New Localization/Translation
- Ensure all UI strings are defined in English resource strings file (
app/src/main/res/values/strings.xml) - Configure language code in Transifex project settings (
.tx/config) - Push strings to Transifex for community translation via tx push (
app/src/main/res/values/strings.xml) - Pull translated strings via tx pull into locale-specific resource directories (
app/src/main/res/values-[locale]/strings.xml)
🔧Why these technologies
- Android SDK + Kotlin — Native access to device sensors (accelerometer, microphone, light sensor, proximity) and background service capabilities.
- Signal Protocol / Tor — End-to-end encryption and anonymous routing to protect alert delivery from surveillance or interception.
- Gradle + Android Gradle Plugin — Standard Android build system; enables reproducible builds and automated CI/CD integration.
- Transifex — Distributed localization platform allowing community translation without compromising the codebase.
⚖️Trade-offs already made
-
On-device sensor processing vs. cloud analytics
- Why: Haven prioritizes user privacy and offline-first operation; all sensor logic runs locally.
- Consequence: No ML-based threat prediction or cross-device learning; simpler threat detection but guaranteed privacy.
-
Supports multiple transport backends (Signal, Tor, WebHooks)
- Why: Users have different threat models and risk profiles; flexibility reduces single point of failure.
- Consequence: Additional transport modules to maintain; users must choose and configure their transport.
-
Requires explicit user permission and launch
- Why: Transparent monitoring respects user agency; avoids hidden background operation that could violate privacy expectations.
- Consequence: Less seamless than always-on monitoring; users must remember to arm the app.
🚫Non-goals (don't propose these)
- Does not provide real-time continuous recording or video streaming.
- Does not include cloud storage or backup of alerts.
- Does not handle authentication or user account management (relies on Signal/Tor for identity).
- Does not provide machine learning-based threat classification.
- Does not support network-based threat detection or intrusion prevention.
⚠️Anti-patterns to avoid
- Hard-coded sensor thresholds or intervals (Medium) —
Assumed in Sensor*Monitor classes (not visible in file list, but likely in app/src/main/java): Sensor sensitivity or sampling rate embedded in code rather than exposed in settings; users cannot tune detection without recompiling. - Synchronous alert transmission —
AlertManager (inferred): undefined
🪤Traps & gotchas
Android SDK 30 is below current stable (33+); may cause emulator issues. No visible Gradle wrapper (./gradlew); Gradle version implicit in CI, requiring manual setup. minSdkVersion 16 (Android 4.1) is very old; sensor availability varies by device. Kotlin/Java mixing suggests package structure inconsistency—find the actual source root layout before modifying. Signal/Tor integration likely requires specific network permissions in AndroidManifest.xml (not visible); test on real device for remote reporting. Weblate config suggests strings.xml is auto-synced; manual edits may be overwritten.
🏗️Architecture
💡Concepts to learn
- Android SensorManager API — Core to Haven—accelerometer, microphone, light sensor polling happens via SensorManager; must understand event-driven sensor callbacks and sampling rates to modify detection logic
- Signal Protocol (Double Ratchet) — Haven uses Signal for end-to-end encrypted alerts; understanding the handshake and ratcheting mechanism explains why remote reports cannot be intercepted by networks
- Tor Hidden Services — Haven routes alerts through Tor; knowing onion routing and .onion endpoint obfuscation explains how the app hides reporter location from ISP-level surveillance
- Android Permissions Model (Runtime & Manifest) — Haven must declare RECORD_AUDIO, ACCESS_ACCELEROMETER, CAMERA, INTERNET in AndroidManifest.xml and request runtime permissions on SDK 23+; critical for understanding privilege escalation and user trust
- View Binding (Android) — build.gradle enables viewBinding true; Haven's modern UIs avoid findViewById() boilerplate and null safety issues; new features should use binding not legacy layouts
- Android Background Services & Foreground Notifications — Haven must keep sensor monitoring alive in background (SDK 26+ enforces Doze mode, battery optimizations); likely uses JobScheduler or Foreground Service with persistent notification
- Threat Modeling for Journalists — Haven's design assumes adversaries with network, device physical access, or signal interception capabilities; understanding its threat model (see README and Intercept article) informs which sensor readings matter and why alerts must be encrypted
🔗Related repos
guardianproject/orbot— Guardian Project's Tor proxy for Android; Haven likely depends on or recommends it for secure Tor routingguardianproject/Signal-Android— Guardian Project's Signal fork (or direct Signal integration); critical for encrypted alert delivery in Havenguardianproject/checkey— Guardian Project's certificate pinning and security auditing app; shared security philosophy and potential model for Haven's threat model validationEFForg/privacybadger— EFF's privacy-focused monitoring (web context); conceptually aligned with Haven's physical-space privacy model for inspiration
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Migrate from deprecated Bintray/JCenter to Maven Central and add Gradle dependency validation
The build.gradle references jcenter() (deprecated/shut down in 2021) and Bintray Kotlin EAP repositories which are no longer reliable. This is a critical infrastructure issue that blocks builds. Migrating to Maven Central and implementing gradle-dependency-check plugin will improve build reliability and prevent future supply chain issues.
- [ ] Remove jcenter() and 'https://dl.bintray.com/kotlin/kotlin-eap/' from buildscript and repositories blocks in build.gradle
- [ ] Add mavenCentral() to repositories and verify Kotlin dependencies resolve correctly
- [ ] Update build.gradle to use stable Kotlin version (currently 1.5.21 from 2021) to a recent LTS release
- [ ] Add gradle-dependency-check plugin to detect vulnerable dependencies and configure in build.gradle
- [ ] Test full build and verify all dependencies resolve without Bintray
Add Android instrumented tests for sensor monitoring core logic
The repo has no visible test files despite being a sensor-based monitoring app with critical privacy implications. The core sensor detection logic (motion, sound, vibration, light) needs test coverage to prevent regressions. Instrumented tests are essential for validating sensor accuracy and alert thresholds across devices.
- [ ] Create androidTest/ directory structure mirroring src/main/java package hierarchy
- [ ] Write instrumented tests for sensor manager initialization and permission handling
- [ ] Add tests for motion/sound/vibration/light detection thresholds and alert triggers
- [ ] Configure build.gradle with testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
- [ ] Add androidx.test dependencies (espresso, runner) to build.gradle and update CI (.travis.yml) to run tests
Create GitHub Actions workflow to replace Travis CI and add F-Droid/Play Store build validation
The .travis.yml config exists but is minimal and Travis CI has reduced free tier support. This repo targets security-conscious users who use F-Droid—building a GitHub Actions workflow that validates APK builds, checks code signing, and verifies F-Droid metadata compliance would improve release quality and developer experience.
- [ ] Create .github/workflows/android-build.yml with steps to build APK using gradlew assembleDebug/Release
- [ ] Add APK signature verification step using apksigner (from Android SDK)
- [ ] Validate F-Droid metadata: check fastlane/android/metadata/en-US/ structure and metadata completeness
- [ ] Add lint/detekt static analysis step to catch code quality issues before merge
- [ ] Set up conditional release artifact uploads on tag creation to compare against existing Travis setup
🌿Good first issues
- Add unit tests for sensor data collection—likely Java sensor handler classes exist (SensorManager wrappers) with no test coverage visible in file list; write tests for edge cases like rapid motion/sound spikes
- Migrate remaining Java Activities to Kotlin—codebase is mixed (255KB Java vs 36KB Kotlin); pick one Activity, convert to Kotlin, and submit; build.gradle shows kotlin-kapt is ready
- Document sensor calibration guide—README mentions motion/sound/vibration/light detection but no technical docs on threshold tuning; add a docs/ file explaining how users should calibrate for their space
⭐Top contributors
Click to expand
Top contributors
- @n8fr8 — 20 commits
- @weblate — 12 commits
- @lukeswitz — 11 commits
- @SantosSi — 4 commits
- [@Oğuz Ersen](https://github.com/Oğuz Ersen) — 4 commits
📝Recent commits
Click to expand
Recent commits
1e070fb— remove donate button for now (n8fr8)ecc46dd— Merge pull request #452 from archie94/webserver_video_download (n8fr8)fa830bb— Serve video event triggers too from Webserver (archie94)cabb16c— Dependency update (archie94)c12acbf— update dependencies (n8fr8)a9feffe— update gradle build mem usage (n8fr8)54628c5— update gradle (n8fr8)4ce95c3— Merge branch 'master' of github.com:guardianproject/haven (n8fr8)03d4cf2— update gradle to work with latest Android Studio beta (n8fr8)e378136— udpate gradle (n8fr8)
🔒Security observations
- High · Outdated Gradle and Build Tools —
build.gradle. The build.gradle file uses Gradle 4.2.2 (classpath 'com.android.tools.build:gradle:4.2.2') which is significantly outdated and contains known security vulnerabilities. This version was released in 2021 and has not received security updates for years. The compileSdkVersion 30 and targetSdkVersion 30 are also outdated (current is 34+), missing modern security features and privacy enhancements. Fix: Update to the latest Gradle version (8.x) and Android Gradle Plugin (8.x). Update compileSdkVersion and targetSdkVersion to 34 or higher. Test thoroughly with new versions for compatibility. - High · Outdated Kotlin Version —
build.gradle (ext.kotlin_version = '1.5.21'). Kotlin version 1.5.21 is outdated and no longer receives security updates. Current stable versions are 1.9.x and above. Outdated Kotlin versions may have known security issues and lack modern language features that improve code safety. Fix: Update to the latest stable Kotlin version (1.9.x or 2.0+). Review release notes for breaking changes and test accordingly. - High · Insecure Repository Configuration —
build.gradle (maven { url 'https://dl.bintray.com/kotlin/kotlin-eap/' }). The build configuration includes the deprecated Bintray Maven repository (dl.bintray.com/kotlin/kotlin-eap/) which is no longer maintained. Bintray was shut down in 2021. Using deprecated repositories can expose the project to malicious or compromised artifacts. Fix: Remove Bintray repositories. Use only official repositories: Maven Central, Google Maven, and JitPack for verified projects. Replace with Maven Central or Google's official Kotlin EAP repository if needed. - Medium · JCenter Repository Deprecated —
build.gradle (repositories block). The build file references 'jcenter()' which was deprecated and shut down. While it may still work through redirects, this is an unstable dependency source that could fail or be compromised. Fix: Remove jcenter() and rely on Google Maven Repository and Maven Central exclusively. - Medium · Insufficient Minify Configuration —
build.gradle. No explicit ProGuard/R8 minification rules are visible in the provided build configuration. For a security-sensitive application like Haven that handles sensor data and privacy, code obfuscation should be properly configured to prevent reverse engineering. Fix: Configure R8/ProGuard minification rules. Add a proguard-rules.pro file with rules to obfuscate sensitive classes. Enable minification for release builds. - Medium · Missing Security Lint Checks —
build.gradle (commented-out gradle.projectsEvaluated block). The security lint checks are commented out in the build configuration ('gradle.projectsEvaluated' block is disabled). These checks help identify potential security issues at compile time. Fix: Enable and configure lint security checks. Uncomment and properly configure compiler warnings for security issues. Add 'android.lintOptions.checkReleaseBuilds = true'. - Low · Potential Version String Injection Risk —
build.gradle (getVersionName function). The version name is derived from git tags via shell execution: 'exec { commandLine 'git', 'describe', '--tags', '--always', '--abbrev=0' }'. While relatively safe here, dynamic version generation via shell execution could be a vector for injection if not properly validated. Fix: Validate the git output to ensure it matches expected version format (e.g., semantic versioning). Consider using a static version file instead of dynamic git tag parsing. - Low · No Signing Configuration Visible —
build.gradle. No release signing configuration is visible in the provided build.gradle file. For a security-focused application, proper APK signing configuration should be explicitly defined and securely managed. Fix: Add explicit signingConfigs block with proper keystore configuration for release builds. Store keystore credentials in a secure, non-versioned location. Use gradle.properties or Android keystore system.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.