fix(android): restore Play privacy policy URL
This commit is contained in:
@@ -4,11 +4,13 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "legacy-pages-redirect/**"
|
||||
- "website/public/privacy.html"
|
||||
- ".github/workflows/legacy-docs-redirect.yml"
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "legacy-pages-redirect/**"
|
||||
- "website/public/privacy.html"
|
||||
- ".github/workflows/legacy-docs-redirect.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -34,10 +36,12 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source_file="legacy-pages-redirect/redirect.html"
|
||||
privacy_file="website/public/privacy.html"
|
||||
output_dir="legacy-pages-redirect/_site"
|
||||
rm -rf "$output_dir"
|
||||
mkdir -p \
|
||||
"$output_dir/guide/getting-started" \
|
||||
"$output_dir/privacy" \
|
||||
"$output_dir/reference/relay-server" \
|
||||
"$output_dir/architecture"
|
||||
for target in \
|
||||
@@ -50,8 +54,12 @@ jobs:
|
||||
architecture/connection-security.html; do
|
||||
cp "$source_file" "$output_dir/$target"
|
||||
done
|
||||
cp "$privacy_file" "$output_dir/privacy.html"
|
||||
cp "$privacy_file" "$output_dir/privacy/index.html"
|
||||
touch "$output_dir/.nojekyll"
|
||||
test "$(find "$output_dir" -type f | wc -l)" -eq 8
|
||||
test "$(find "$output_dir" -type f | wc -l)" -eq 10
|
||||
grep -Fq '<h1>Privacy Policy</h1>' "$output_dir/privacy.html"
|
||||
grep -Fq 'https://hermes-relay.dev/privacy.html' "$output_dir/privacy.html"
|
||||
if grep -R -E '<title>VitePress|<div id="app">' "$output_dir"; then
|
||||
echo "Full documentation content must not be deployed by this workflow." >&2
|
||||
exit 1
|
||||
|
||||
@@ -81,6 +81,7 @@ jobs:
|
||||
- name: Validate release metadata and source compatibility
|
||||
run: |
|
||||
python3 scripts/check-version-tracks.py
|
||||
python3 scripts/check-privacy-policy.py --live
|
||||
python3 scripts/check-android-locales.py
|
||||
python3 scripts/check-android-collection-apis.py
|
||||
python3 -m json.tool app/src/main/assets/changelog.json >/dev/null
|
||||
|
||||
@@ -74,6 +74,9 @@ jobs:
|
||||
|
||||
echo "Version validated: $TAG_VERSION"
|
||||
|
||||
- name: Verify public privacy policy URLs
|
||||
run: python3 scripts/check-privacy-policy.py --live
|
||||
|
||||
- name: Verify tagged commit belongs to main
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -123,6 +126,7 @@ jobs:
|
||||
- name: Validate release metadata and Android API compatibility
|
||||
run: |
|
||||
python3 scripts/check-version-tracks.py
|
||||
python3 scripts/check-privacy-policy.py
|
||||
python3 scripts/check-android-locales.py
|
||||
python3 scripts/check-android-collection-apis.py
|
||||
|
||||
|
||||
@@ -10,6 +10,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
|
||||
|
||||
- **Relay trust boundaries are enforced across privileged interfaces.** Pairing policy is host-authorized, Android bridge and terminal dispatch require active grants, ordinary sessions can only reduce their own policy, remote profile config is restricted to a public schema, and voice callers cannot redirect host provider credentials.
|
||||
|
||||
## [1.4.8] - 2026-07-18
|
||||
|
||||
### Fixed
|
||||
|
||||
- **The Google Play privacy-policy URL is permanently available.** The canonical policy now lives on hermes-relay.dev, the historical GitHub Pages URL serves the complete policy for compatibility, and Android release automation blocks publication if either public page is unavailable.
|
||||
- **Android opens the hosted privacy policy directly.** The About screen no longer sends users to a repository source file.
|
||||
|
||||
## [1.4.7] - 2026-07-18
|
||||
|
||||
### Added
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# Hermes-Relay — Dev Log
|
||||
|
||||
## 2026-07-18 — Android privacy-policy URL hotfix
|
||||
|
||||
The canonical Android privacy policy moved to a stable public page on
|
||||
hermes-relay.dev. The historical GitHub Pages path now serves the complete
|
||||
policy for compatibility with existing store metadata instead of depending on
|
||||
a client-side redirect. Android's About screen, public privacy references, and
|
||||
Play submission documentation use the canonical site URL.
|
||||
|
||||
The legacy Pages workflow publishes both file and directory policy paths from
|
||||
the same canonical HTML source. Repository validation checks the policy's
|
||||
required disclosures and URL wiring, while Play preflight and stable tag release
|
||||
jobs additionally require both deployed policy URLs to return complete policy
|
||||
content before an artifact can be uploaded or promoted. Android advanced to
|
||||
1.4.8 with versionCode 31 for the replacement Play submission.
|
||||
|
||||
## 2026-07-18 — Android 1.4.7 release preparation
|
||||
|
||||
Android advanced to 1.4.7 with versionCode 30 after the localization, streaming,
|
||||
|
||||
+7
-11
@@ -1,10 +1,10 @@
|
||||
# Hermes-Relay-Android v1.4.7
|
||||
# Hermes-Relay-Android v1.4.8
|
||||
|
||||
**Release Date:** July 18, 2026
|
||||
|
||||
## Download
|
||||
|
||||
> Installing on your phone? Download `hermes-relay-1.4.7-sideload-release.apk` and tap it for the full feature set, or install the conservative build from [Google Play](https://play.google.com/store/apps/details?id=com.axiomlabs.hermesrelay).
|
||||
> Installing on your phone? Download `hermes-relay-1.4.8-sideload-release.apk` and tap it for the full feature set, or install the conservative build from [Google Play](https://play.google.com/store/apps/details?id=com.axiomlabs.hermesrelay).
|
||||
|
||||
The `.aab` file is a Play Console upload bundle and cannot be installed by tapping it on a phone.
|
||||
|
||||
@@ -12,19 +12,15 @@ Verify the download against `SHA256SUMS.txt`. See the [sideload guide](https://h
|
||||
|
||||
## Summary
|
||||
|
||||
This patch adds German, Brazilian Portuguese, and Japanese and makes long streamed replies grow smoothly while staying anchored at the latest text.
|
||||
|
||||
## Added
|
||||
|
||||
- Use German, Brazilian Portuguese, or Japanese throughout both Android product flavors.
|
||||
- Language-picker and catalog freshness checks keep every shipped locale aligned with the canonical English resources.
|
||||
This patch restores the public privacy-policy URL required by Google Play and moves the canonical policy to hermes-relay.dev.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Long streamed replies insert text at a display-paced cadence instead of visibly rebuilding the conversation.
|
||||
- The active response remains anchored at the latest text through growth and completion while readers who scroll into history remain undisturbed.
|
||||
- The historical GitHub Pages privacy URL now serves the complete policy instead of returning 404.
|
||||
- The About screen opens the canonical policy on hermes-relay.dev.
|
||||
- Android release automation verifies both public policy URLs before uploading or publishing to Google Play.
|
||||
|
||||
## Install / Verify
|
||||
|
||||
- App version: **1.4.7** (versionCode **30**).
|
||||
- App version: **1.4.8** (versionCode **31**).
|
||||
- Standard Chat and Vanilla Hermes voice continue to work against unmodified upstream Hermes.
|
||||
|
||||
@@ -1 +1 @@
|
||||
Long streamed replies now grow smoothly and stay anchored at the newest text through completion, while scrolling into history preserves your reading position. German, Brazilian Portuguese, and Japanese are now available throughout the app.
|
||||
The privacy policy now lives at hermes-relay.dev, the About screen opens it directly, and release automation verifies the public policy before publishing.
|
||||
|
||||
@@ -1 +1 @@
|
||||
长回复现在会平滑流式显示,并在完成时保持定位到最新文本;向上滚动查看历史记录时仍会保留阅读位置。应用现已支持德语、巴西葡萄牙语和日语。
|
||||
隐私政策现已迁移到 hermes-relay.dev,“关于”页面可直接打开该政策;发布流程会在上线前验证政策页面是否可公开访问。
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.4.8",
|
||||
"title": "Privacy policy restored",
|
||||
"date": "2026-07-18",
|
||||
"sections": [
|
||||
{
|
||||
"header": "Google Play compliance",
|
||||
"bullets": [
|
||||
"The privacy policy now lives at hermes-relay.dev and the historical store URL remains valid for compatibility.",
|
||||
"The About screen opens the hosted policy directly, and releases verify it is publicly available before publishing."
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.4.7",
|
||||
"title": "Smoother replies, more languages",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
v1.4.7 - Smoother replies, more languages
|
||||
v1.4.8 - Privacy policy link restored
|
||||
|
||||
Smooth streaming
|
||||
* Long replies grow steadily and stay anchored at the newest text through completion.
|
||||
* Scrolling into history still leaves your reading position alone.
|
||||
|
||||
More languages
|
||||
* Use German, Brazilian Portuguese, or Japanese throughout the app.
|
||||
* The privacy policy now lives at hermes-relay.dev.
|
||||
* The About screen opens the hosted policy directly.
|
||||
* Release automation verifies the policy is publicly available before publishing.
|
||||
|
||||
@@ -432,7 +432,7 @@ fun AboutScreen(
|
||||
// Privacy policy link
|
||||
OutlinedButton(
|
||||
onClick = {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/Codename-11/hermes-relay/blob/main/docs/privacy.md"))
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://hermes-relay.dev/privacy.html"))
|
||||
context.startActivity(intent)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
|
||||
@@ -85,14 +85,11 @@ This app is a community project and is not affiliated with or endorsed by NousRe
|
||||
Paste into Play Console → **What's new** (≤500 characters):
|
||||
|
||||
```
|
||||
v1.4.7 - Smoother replies, more languages
|
||||
v1.4.8 - Privacy policy link restored
|
||||
|
||||
Smooth streaming
|
||||
* Long replies grow steadily and stay anchored at the newest text through completion.
|
||||
* Scrolling into history preserves your reading position.
|
||||
|
||||
More languages
|
||||
* Use German, Brazilian Portuguese, or Japanese throughout the app.
|
||||
* The privacy policy now lives at hermes-relay.dev.
|
||||
* The About screen opens the hosted policy directly.
|
||||
* Releases verify the public policy before publishing.
|
||||
```
|
||||
|
||||
## Category
|
||||
@@ -134,6 +131,15 @@ path-filtered Play Store Listing workflow or publish locally with:
|
||||
|
||||
Submission-time declarations the Play Console requires — keep in sync with the merged `googlePlay` manifest.
|
||||
|
||||
### Privacy policy
|
||||
|
||||
Use `https://hermes-relay.dev/privacy.html` as the Play Console privacy-policy
|
||||
URL. The Android preflight and release workflows require both that canonical
|
||||
page and the historical GitHub Pages compatibility URL to return the complete
|
||||
policy before they can publish. The standard Android Publisher listing API does
|
||||
not expose this Play policy-declaration field, so the legacy URL remains a
|
||||
permanent compatibility page for existing Console metadata.
|
||||
|
||||
### App access
|
||||
|
||||
Hermes-Relay is a client for a **user-run Hermes server**. A fresh install with no server configured has no content of its own — which is what a reviewer hits first, and what triggered the v1.2.4 *App access* rejection. The core experience is reviewable **offline via Demo mode**, with **no test server, account, or credentials required**.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
appVersionName = "1.4.7"
|
||||
appVersionCode = "30"
|
||||
appVersionName = "1.4.8"
|
||||
appVersionCode = "31"
|
||||
agp = "9.3.0"
|
||||
kotlin = "2.4.10"
|
||||
compose-bom = "2026.06.01"
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
This directory is a temporary compatibility shim for Android releases that
|
||||
hardcoded `https://codename-11.github.io/hermes-relay/` before PR #210.
|
||||
Documentation is hosted only at `https://hermes-relay.dev/docs/`; GitHub Pages
|
||||
serves redirect HTML and no documentation content.
|
||||
serves redirect HTML for old documentation paths. The historical
|
||||
`privacy.html` URL serves the complete policy from the canonical
|
||||
`website/public/privacy.html` source so store-review crawlers and installed
|
||||
clients never depend on JavaScript redirects.
|
||||
|
||||
The deployment workflow copies `redirect.html` to the project root, the Pages
|
||||
404 fallback, and the exact deep-link paths embedded in released clients. The
|
||||
JavaScript preserves the path, query string, and fragment while moving the
|
||||
request under `/docs/`. The meta refresh and visible link provide a no-script
|
||||
fallback to the guide root.
|
||||
fallback to the guide root. Privacy compatibility pages identify
|
||||
`https://hermes-relay.dev/privacy.html` as canonical.
|
||||
|
||||
Removal is tracked in the repository root `TODO.md`. Do not delete this shim
|
||||
solely because the first fixed release has shipped; honor the documented
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate the canonical and legacy Hermes-Relay privacy policy surfaces."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
CANONICAL_URL = "https://hermes-relay.dev/privacy.html"
|
||||
LEGACY_URL = "https://codename-11.github.io/hermes-relay/privacy.html"
|
||||
REQUIRED_MARKERS = (
|
||||
"<h1>Privacy Policy</h1>",
|
||||
"Google Play build",
|
||||
"Data storage",
|
||||
"Network connections",
|
||||
"Data export and deletion",
|
||||
"Children's privacy",
|
||||
"Hermes-Relay issue tracker",
|
||||
)
|
||||
|
||||
|
||||
def validate_content(label: str, content: str) -> None:
|
||||
missing = [marker for marker in REQUIRED_MARKERS if marker not in content]
|
||||
if missing:
|
||||
raise ValueError(f"{label} is missing required markers: {', '.join(missing)}")
|
||||
|
||||
|
||||
def validate_repository() -> None:
|
||||
policy = (ROOT / "website/public/privacy.html").read_text(encoding="utf-8")
|
||||
validate_content("website/public/privacy.html", policy)
|
||||
if f'<link rel="canonical" href="{CANONICAL_URL}"' not in policy:
|
||||
raise ValueError("canonical privacy URL is missing from website/public/privacy.html")
|
||||
|
||||
about = (ROOT / "app/src/main/kotlin/com/hermesandroid/relay/ui/screens/AboutScreen.kt").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
if CANONICAL_URL not in about:
|
||||
raise ValueError("Android About screen does not use the canonical privacy URL")
|
||||
|
||||
workflow = (ROOT / ".github/workflows/legacy-docs-redirect.yml").read_text(encoding="utf-8")
|
||||
for marker in ("website/public/privacy.html", "privacy.html", "privacy/index.html"):
|
||||
if marker not in workflow:
|
||||
raise ValueError(f"legacy Pages workflow is missing {marker}")
|
||||
|
||||
|
||||
def fetch(url: str) -> str:
|
||||
request = urllib.request.Request(url, headers={"User-Agent": "Hermes-Relay-release-check/1"})
|
||||
try:
|
||||
with urllib.request.urlopen(request, timeout=30) as response:
|
||||
if response.status != 200:
|
||||
raise ValueError(f"{url} returned HTTP {response.status}")
|
||||
return response.read().decode("utf-8")
|
||||
except urllib.error.HTTPError as error:
|
||||
raise ValueError(f"{url} returned HTTP {error.code}") from error
|
||||
except urllib.error.URLError as error:
|
||||
raise ValueError(f"{url} could not be loaded: {error.reason}") from error
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--live", action="store_true", help="also validate deployed policy URLs")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
validate_repository()
|
||||
if args.live:
|
||||
for url in (CANONICAL_URL, LEGACY_URL):
|
||||
validate_content(url, fetch(url))
|
||||
except ValueError as error:
|
||||
print(f"privacy policy validation failed: {error}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
suffix = " and live URLs" if args.live else ""
|
||||
print(f"privacy policy repository contract{suffix} validated")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -42,4 +42,4 @@ From **Settings**, you can export a full connection backup, import a backup, or
|
||||
|
||||
## Open source
|
||||
|
||||
All code is [MIT licensed](https://github.com/Codename-11/hermes-relay) and publicly auditable. See the full privacy document at [`docs/privacy.md`](https://github.com/Codename-11/hermes-relay/blob/main/docs/privacy.md).
|
||||
All code is [MIT licensed](https://github.com/Codename-11/hermes-relay) and publicly auditable. See the full [privacy policy](https://hermes-relay.dev/privacy.html).
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Privacy policy for the Hermes-Relay Android app
|
||||
|
||||
# Privacy Policy
|
||||
|
||||
**Hermes-Relay** · Effective date: May 19, 2026
|
||||
**Hermes-Relay** · Effective date: July 18, 2026
|
||||
|
||||
Hermes-Relay is a native Android app that connects to your own [Hermes Agent](https://github.com/NousResearch/hermes-agent) host. This policy describes how the app handles your data.
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="description" content="Privacy policy for the Hermes-Relay Android app" />
|
||||
<link rel="canonical" href="https://hermes-relay.dev/privacy.html" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="Privacy Policy | Hermes-Relay" />
|
||||
<meta property="og:description" content="Privacy policy for the Hermes-Relay Android app" />
|
||||
<meta property="og:url" content="https://hermes-relay.dev/privacy.html" />
|
||||
<meta property="og:image" content="https://hermes-relay.dev/social-card.png" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<script type="application/ld+json">
|
||||
{"@context":"https://schema.org","@type":"WebPage","name":"Hermes-Relay Privacy Policy","url":"https://hermes-relay.dev/privacy.html","isPartOf":{"@type":"WebSite","name":"Hermes-Relay","url":"https://hermes-relay.dev/"}}
|
||||
</script>
|
||||
<title>Privacy Policy | Hermes-Relay</title>
|
||||
<style>
|
||||
:root { color-scheme: light dark; font-family: system-ui, sans-serif; line-height: 1.6; }
|
||||
body { margin: 0; background: #111019; color: #f4f0ff; }
|
||||
main { width: min(48rem, calc(100% - 2rem)); margin: 0 auto; padding: 3rem 0 5rem; }
|
||||
a { color: #c5a7ff; }
|
||||
h1, h2 { line-height: 1.2; }
|
||||
h2 { margin-top: 2.25rem; }
|
||||
.summary { padding: 1rem 1.25rem; border: 1px solid #584b72; border-radius: 0.75rem; background: #191624; }
|
||||
table { width: 100%; border-collapse: collapse; display: block; overflow-x: auto; }
|
||||
th, td { padding: 0.65rem; border: 1px solid #584b72; text-align: left; vertical-align: top; }
|
||||
footer { margin-top: 3rem; color: #bdb5ca; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Privacy Policy</h1>
|
||||
<p><strong>Hermes-Relay</strong> · Effective date: July 18, 2026</p>
|
||||
|
||||
<section class="summary">
|
||||
<h2>Summary</h2>
|
||||
<p>Hermes-Relay does not collect, transmit, or share personal data with third parties. The app connects only to servers that you configure. There are no accounts, no hosted Hermes-Relay cloud service, and no externally transmitted analytics.</p>
|
||||
</section>
|
||||
|
||||
<h2>Google Play build</h2>
|
||||
<p>The Google Play build ships Hermes Bridge Core: chat, voice, terminal and TUI relay, notification companion, media handoff, relay sessions, and status. It does not include AccessibilityService-based Device Control and cannot read your screen, tap, type, swipe, capture screenshots, send SMS, place calls, access contacts or location, or perform unattended phone control.</p>
|
||||
<p>The sideload build is a separate distribution track for users who intentionally install Device Control outside Google Play.</p>
|
||||
|
||||
<h2>Data storage</h2>
|
||||
<p>All data is stored locally on your device in the app's private sandbox.</p>
|
||||
<table>
|
||||
<thead><tr><th>Data</th><th>Storage method</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Server URLs and preferences</td><td>Android DataStore (app-private)</td></tr>
|
||||
<tr><td>API keys and relay session tokens</td><td>AES-256-GCM encryption via Android Keystore</td></tr>
|
||||
<tr><td>Performance counters</td><td>Android DataStore (local only)</td></tr>
|
||||
<tr><td>Notification trigger rules and activity log</td><td>Android DataStore (local only)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Chat messages are not cached on your device. They are loaded from your Hermes server on demand and exist only in memory while the app is running.</p>
|
||||
|
||||
<h2>Network connections</h2>
|
||||
<p>The app connects only to endpoints you configure: your Hermes API server for chat streaming; your relay server for terminal and TUI relay, Bridge Core status, media handoff, notification companion, and session management; and your relay voice routes when you use Voice mode.</p>
|
||||
<p>No connections are made to Google, Anthropic, or any other third-party service by the app. There is no telemetry, advertising, external crash reporting, DNS prefetching, or background network activity to hosted Hermes-Relay services. Your Hermes server may separately connect to AI providers according to its configuration; that server-side activity is outside the scope of this app.</p>
|
||||
|
||||
<h2>Permissions</h2>
|
||||
<table>
|
||||
<thead><tr><th>Permission or access</th><th>Purpose</th><th>Required</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Internet</td><td>Connect to your Hermes servers</td><td>Yes</td></tr>
|
||||
<tr><td>Network state</td><td>Detect connectivity for reconnect behavior</td><td>Yes</td></tr>
|
||||
<tr><td>Camera</td><td>QR code scanning for server pairing</td><td>No</td></tr>
|
||||
<tr><td>Microphone</td><td>Voice mode speech-to-text</td><td>No</td></tr>
|
||||
<tr><td>Notification access</td><td>Optional notification companion metadata forwarding to your paired relay</td><td>No</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Notification access is granted and revoked from Android system settings. When enabled, Hermes-Relay forwards posted-notification package, title, text, subtext, timestamp, and notification key to your paired relay. It does not forward notifications to a Hermes-Relay cloud service. Optional notification-trigger matching happens locally on the phone and does not automatically send an AI request or reply in another app.</p>
|
||||
|
||||
<h2>Third-party services</h2>
|
||||
<p>Hermes-Relay includes no advertising, tracking, or analytics services. The app is built with Android platform components and open-source libraries.</p>
|
||||
|
||||
<h2>Data export and deletion</h2>
|
||||
<p>From Settings, you can export a connection backup, import a saved configuration, or perform a full reset. Exported backups can include server URLs, preferences, API keys, relay session tokens, device IDs, and dashboard cookies, so keep them private. Full reset permanently deletes local data including encrypted credentials. Uninstalling the app removes all stored app data from your device.</p>
|
||||
|
||||
<h2>Children's privacy</h2>
|
||||
<p>Hermes-Relay is not directed at children under 13. We do not knowingly collect information from children.</p>
|
||||
|
||||
<h2>Changes to this policy</h2>
|
||||
<p>Updates will be posted on this page with a revised effective date. Significant changes will be noted in the app's release notes.</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>For privacy questions, open an issue in the <a href="https://github.com/Codename-11/hermes-relay/issues">Hermes-Relay issue tracker</a>.</p>
|
||||
|
||||
<h2>Open source</h2>
|
||||
<p>Hermes-Relay is <a href="https://github.com/Codename-11/hermes-relay">MIT licensed and publicly auditable</a>.</p>
|
||||
|
||||
<footer><a href="https://hermes-relay.dev/">Return to hermes-relay.dev</a></footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,6 +12,7 @@ const localeByRelativePath = new Map([
|
||||
[join('pt-BR', 'index.html'), 'pt-BR'],
|
||||
[join('zh-CN', 'index.html'), 'zh-CN'],
|
||||
]);
|
||||
const expectedHtmlPaths = new Set([...localeByRelativePath.keys(), 'privacy.html']);
|
||||
|
||||
async function walk(directory) {
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
@@ -90,8 +91,12 @@ for (const htmlPath of htmlFiles) {
|
||||
}
|
||||
}
|
||||
|
||||
if (htmlFiles.length !== localeByRelativePath.size) {
|
||||
failures.push(`expected ${localeByRelativePath.size} localized HTML pages, found ${htmlFiles.length}`);
|
||||
const actualHtmlPaths = new Set(htmlFiles.map((path) => path.slice(distRoot.length + 1)));
|
||||
for (const expectedPath of expectedHtmlPaths) {
|
||||
if (!actualHtmlPaths.has(expectedPath)) failures.push(`missing expected HTML page ${expectedPath}`);
|
||||
}
|
||||
for (const actualPath of actualHtmlPaths) {
|
||||
if (!expectedHtmlPaths.has(actualPath)) failures.push(`unexpected HTML page ${actualPath}`);
|
||||
}
|
||||
|
||||
if (failures.length) {
|
||||
|
||||
Reference in New Issue
Block a user