fix(docs): route Wowlet support to Wownero contacts

This commit is contained in:
2026-10-16 14:27:59 -04:00
parent f4bbfd49ad
commit 66c16d152d
6 changed files with 156 additions and 87 deletions
+4 -1
View File
@@ -13,4 +13,7 @@ clean:
DEFAULT_GOAL := default DEFAULT_GOAL := default
default: build default: build
.PHONY: default build attest verify clean check:
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s contrib/docs/tests -v
.PHONY: default build attest verify clean check
+25 -45
View File
@@ -1,60 +1,40 @@
# Feather Wallet # Wowlet
Feather is a free Monero desktop wallet for Linux, Tails, macOS and Windows. It is written in C++ with the Qt framework. Wowlet is a Wownero desktop wallet for Linux, macOS and Windows, built with C++ and
Qt. It is based on [Feather Wallet](https://github.com/feather-wallet/feather).
- **easy-to-use**, **small** and **fast** - Feather runs well on any modern hardware, including virtual machines and live operating systems.
- **beginner friendly**, but also caters to advanced Monero users by providing a [feature set](https://docs.featherwallet.org/guides/features) that is on par with the official CLI.
- ships with **sane defaults** that suit most users, but can also be configured for high or uncommon threat models.
- serves as a testing grounds for **experimental features** that may later be adopted in the reference wallets.
## Download ## Download
You can download Feather from **[featherwallet.org](https://featherwallet.org/download/)** or **[GitHub](https://github.com/feather-wallet/feather/releases)**. Download Wowlet and its signed release hashes from
[Wowlet releases](https://github.com/wownero/wowlet/releases). The desktop wallet
link on [wownero.org](https://wownero.org/) also leads there.
If you need help installing Feather, check the [installation documentation](https://docs.featherwallet.org/). ## Support
We recommend that you verify downloads with GPG. Releases are signed with our [release signing key](https://docs.featherwallet.org/guides/release-signing-key). The fingerprint is: - Matrix: [#wownero-gen:wowne.ro](https://matrix.to/#/#wownero-gen:wowne.ro)
- IRC: `#wownero` on [OFTC](https://www.oftc.net/), or use
[webchat](https://webchat.oftc.net/?randomnick=1&channels=wownero)
- Email: [wownero@wownero.org](mailto:wownero@wownero.org)
- Bug reports: [Wowlet issues](https://github.com/wownero/wowlet/issues)
``` If nobody replies immediately, stay in the room and give volunteers time to respond.
8185 E158 A333 30C7 FD61 BC0D 1F76 E155 CEFB A71C Include your Wowlet version, operating system, reproduction steps and any error
``` message. Never share your wallet seed, private keys, password or wallet files.
Windows releases are code-signed for free by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/). Report vulnerabilities privately using [SECURITY.md](SECURITY.md).
## Resources
* [Official Site](https://featherwallet.org)
* [Documentation](https://docs.featherwallet.org)
* [Git Repository](https://github.com/feather-wallet/feather)
* [Matrix](https://matrix.to/#/#feather:monero.social)
* IRC: `#feather` on [OFTC](https://www.oftc.net/)
* Mail: dev@featherwallet.org
If you need help with your wallet, please contact us via Matrix or IRC.
If you don't have an IRC client, you can join the room via [webchat](https://webchat.oftc.net/?randomnick=1&channels=feather).
If you don’t receive a response immediately please idle in the room.
## Release Builds
To learn how to run a bootstrappable release build, see: [contrib/guix/README.md](https://github.com/feather-wallet/feather/blob/master/contrib/guix/README.md)
For release attestations, see the [feather-sigs](http://github.com/feather-wallet/feather-sigs) repo.
For release policy, see: [RELEASE.md](https://github.com/feather-wallet/feather/blob/master/RELEASE.md)
## Development ## Development
If you are looking to set up a development environment for Feather, see [HACKING.md](https://github.com/feather-wallet/feather/blob/master/HACKING.md). The application includes an offline documentation browser under Help. Its guides
are generated by `contrib/docs/generate.py` from the Feather documentation submodule.
Wowlet-specific guides in `contrib/docs/overrides` take precedence over upstream
guides with the same filename. Edit those sources, then regenerate; files under
`src/assets/docs` are generated and must not be edited directly.
It is highly recommended that you join our Matrix or IRC channel if you are hacking on Feather. Run the documentation regression checks with `make check`. The inherited build
Idling in this channel is the best way to stay updated on best practices and new developments. instructions are in [HACKING.md](HACKING.md).
For information on how Feather is maintained, see: [MAINTENANCE.md](https://github.com/feather-wallet/feather/blob/master/MAINTENANCE.md)
To report a security vulnerability, see: [SECURITY.md](https://github.com/feather-wallet/feather/blob/master/SECURITY.md)
## License ## License
Feather is free and open-source software, [licensed under BSD-3](https://raw.githubusercontent.com/feather-wallet/feather/master/LICENSE). Wowlet is free and open-source software under [BSD-3-Clause](LICENSE).
Upstream copyright notices are retained in the source.
Copyright (c) 2020-2025, The Monero Project
+7 -39
View File
@@ -2,43 +2,11 @@
## Reporting a Vulnerability ## Reporting a Vulnerability
Please do not open an issue to report security issues. Report Wowlet security vulnerabilities privately to
[wownero@wownero.org](mailto:wownero@wownero.org).
Please do not disclose them in public issues or community chat before the
maintainers have had time to investigate.
To report a vulnerability email to dev@featherwallet.org Include the affected Wowlet version, operating system, expected impact and steps
to reproduce the issue. Use a disposable wallet for any reproduction and never
The following keys may be used to communicate sensitive information to developers: send a real wallet seed, private keys, password or wallet files.
| Name | Fingerprint |
|---------|---------------------------------------------------|
| tobtoht | E87B D921 CDD8 85C9 D78A 38C5 E45B 10DD 027D 2472 |
Public keys can be found in [`utils/pubkeys`](utils/pubkeys).
## Bug Bounty Program
A bounty may be rewarded to a vulnerability report **if and only if** the issue can result in **a loss of funds**.
You must describe a **plausible scenario** in which a loss of funds can occur (or has occurred) that **isn't solely attributable to user error**.
Only **the code** of the **latest tagged release** of **[this repository](https://github.com/feather-wallet/feather/)** is in scope.
**The bounty can only be rewarded in XMR**. The bounty amount for your report is determined by the maintainers and ranges from USD 150 to USD 3000 (in terms of XMR) and depends on the severity of the issue and other factors.
Clarifications on scope:
- The issue **must be present in a [signed](https://docs.featherwallet.org/guides/release-signing-key) [release build](https://github.com/feather-wallet/feather/blob/master/contrib/guix/README.md)**. Custom builds, including distribution packages, are out of scope.
- The developers **must be able to reproduce and fix the issue**. If the issue cannot be fixed **in our code** for any reason, it is out of scope.
- The live [websites](https://github.com/feather-wallet/feather-site/blob/master/mirrors.txt) and their repositories are out of scope.
- Loss of funds due to malware on the user's machine is out of scope.
- Memory imaging, including cold boot attacks, is out of scope.
- Social engineering against users is out of scope. This includes messages received from the [websocket server](https://docs.featherwallet.org/guides/websocket).
- Any form of coercion, physical or psychological, is out of scope.
- Vulnerabilities that are attributable to hardware are out of scope.
- If the issue was fixed in the `master` branch before we receive your report, it is invalid and not eligible for a bounty from this program.
- If the vulnerability involves binary exploitation, we may ask you to provide a proof of concept of secret key exfiltration.
- Vulnerabilities that are present in the monero submodule but were not introduced in patches made by the Feather developers must
be reported [upstream](https://github.com/monero-project/meta/blob/master/VULNERABILITY_RESPONSE_PROCESS.md) and are not eligible for a bounty from this program.
- Vulnerabilities that are present in any of our third-party dependencies must be reported upstream and are not eligible for a bounty from this program.
- Vulnerabilities that are present in [supported hardware wallets](https://docs.featherwallet.org/guides/hardware-wallet-support) must be reported upstream and are not eligible for a bounty from this program.
- A bounty will not be awarded if the reported vulnerability was already known. We may make an exception if you demonstrate that the severity of the issue was underestimated and no immediate fix was planned.
- If, during your research, you disrupt Feather's release infrastructure or services, or attempt to coerce its developers, you will not be awarded a bounty.
+6 -2
View File
@@ -2,6 +2,7 @@ import os
import glob import glob
DOCS_DIR = "external/feather-docs/content/_guides" DOCS_DIR = "external/feather-docs/content/_guides"
OVERRIDES_DIR = "contrib/docs/overrides"
OUT_DIR = "src/assets/docs" OUT_DIR = "src/assets/docs"
CATEGORY_MAP = { CATEGORY_MAP = {
@@ -21,9 +22,12 @@ outfiles = glob.glob(f"{OUT_DIR}/*.md")
for file in outfiles: for file in outfiles:
os.remove(file) os.remove(file)
files = glob.glob(f"{DOCS_DIR}/*.md") # Wowlet owns its support contacts. Local sources take precedence so regenerating
# the bundled docs cannot restore Feather's contact details.
files = {os.path.basename(path): path for path in glob.glob(f"{DOCS_DIR}/*.md")}
files.update({os.path.basename(path): path for path in glob.glob(f"{OVERRIDES_DIR}/*.md")})
for file in files: for file in sorted(files.values()):
with open(file) as f: with open(file) as f:
doc = f.read() doc = f.read()
+29
View File
@@ -0,0 +1,29 @@
---
title: "How to report an issue"
nav_title: "Report an issue"
category: "help"
---
For help with Wowlet, contact the Wownero community:
- Matrix: [#wownero-gen:wowne.ro](https://matrix.to/#/#wownero-gen:wowne.ro)
- IRC: `#wownero` on [OFTC](https://www.oftc.net/)
- Email: [wownero@wownero.org](mailto:wownero@wownero.org)
- Bug reports: [Wowlet issues](https://github.com/wownero/wowlet/issues)
For live support, use Matrix or IRC. If you do not have an IRC client, join
[#wownero in your browser](https://webchat.oftc.net/?randomnick=1&channels=wownero).
If nobody replies immediately, stay in the room and give volunteers time to respond.
Please include your Wowlet version, operating system, the steps that caused the
problem, and any error message. Review **Help → Debug Info** before sharing it and
remove any personal information. Never share your wallet seed, private keys or
password, and do not upload your wallet files.
Report security vulnerabilities privately to
[wownero@wownero.org](mailto:wownero@wownero.org), rather than in a public issue or
chat. See the [Wowlet security policy](https://github.com/wownero/wowlet/blob/master/SECURITY.md).
Downloads and signed release hashes are available from
[Wowlet releases](https://github.com/wownero/wowlet/releases), also linked from
[wownero.org](https://wownero.org/).
+85
View File
@@ -0,0 +1,85 @@
import re
import shutil
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
from urllib.parse import parse_qs, urlsplit
ROOT = Path(__file__).resolve().parents[3]
class GenerateDocsTests(unittest.TestCase):
def setUp(self):
self.directory = tempfile.TemporaryDirectory()
self.addCleanup(self.directory.cleanup)
self.root = Path(self.directory.name)
self.upstream = self.root / "external/feather-docs/content/_guides"
self.upstream.mkdir(parents=True)
self.output = self.root / "src/assets/docs"
self.output.mkdir(parents=True)
shutil.copytree(ROOT / "contrib/docs/overrides", self.root / "contrib/docs/overrides")
def write_upstream(self, name, body):
(self.upstream / name).write_text(
'---\ntitle: "Upstream guide"\nnav_title: "Upstream"\ncategory: "help"\n---\n'
+ body
)
def generate(self):
result = subprocess.run(
[sys.executable, "-B", str(ROOT / "contrib/docs/generate.py")],
cwd=self.root, capture_output=True, text=True,
)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
def assert_wownero_contacts(self, document):
urls = [urlsplit(url) for url in re.findall(r"\]\(([^)]+)\)", document)]
self.assertTrue(any(
url.hostname == "matrix.to" and url.fragment == "/#wownero-gen:wowne.ro"
for url in urls
), "Matrix must lead to Wownero's published room")
self.assertTrue(any(
url.hostname == "webchat.oftc.net"
and "wownero" in parse_qs(url.query).get("channels", [])
for url in urls
), "Webchat must join Wownero's IRC channel")
self.assertTrue(any(
url.hostname == "github.com" and url.path == "/wownero/wowlet/issues"
for url in urls
), "Bug reports must go to the Wowlet tracker")
self.assertTrue(any(
url.scheme == "mailto" and url.path == "wownero@wownero.org"
for url in urls
), "Email must reach the published Wownero contact")
for url in urls:
self.assertNotIn("feather", url.geturl().lower(), "Support must not route to Feather")
def test_support_override_survives_regeneration(self):
self.write_upstream("report_an_issue.md", "Upstream support contacts")
self.write_upstream("accounts.md", "An upstream guide without an override")
(self.output / "stale.md").write_text("Obsolete generated guide")
for body in ("Upstream support contacts", "Changed upstream support contacts"):
self.write_upstream("report_an_issue.md", body)
self.generate()
support = (self.output / "report_an_issue.md").read_text()
self.assert_wownero_contacts(support)
self.assertNotIn(body, support)
self.assertRegex(support, r"(?m)^\[nav_title\]: # \(.+\)$")
self.assertRegex(support, r"(?m)^\[category\]: # \(.+\)$")
self.assertIn("An upstream guide without an override", (self.output / "accounts.md").read_text())
self.assertFalse((self.output / "stale.md").exists())
def test_readme_and_security_contacts_agree_with_bundled_help(self):
readme = (ROOT / "README.md").read_text()
support = readme.split("## Support\n", 1)[1].split("\n## ", 1)[0]
self.assert_wownero_contacts(support)
policy = (ROOT / "SECURITY.md").read_text()
self.assertIn("mailto:wownero@wownero.org", policy)
self.assertNotIn("featherwallet.org", policy)
if __name__ == "__main__":
unittest.main()