The README shows what each verification badge means (#6)

Co-authored-by: Danny Kim <temeddix@gmail.com>
Co-committed-by: Danny Kim <temeddix@gmail.com>
This commit was merged in pull request #6.
This commit is contained in:
Danny Kim
2026-09-25 20:17:21 +00:00
committed by temeddix
parent bf0e4561c0
commit 967f257902
8 changed files with 51 additions and 16 deletions
+50 -15
View File
@@ -12,14 +12,20 @@ It registers one provider, `signature`, for the `signed-webdav` scheme.
## Connecting
| Field | Meaning |
| --- | --- |
| Server address | The folder's address, for example `https://dav.example.com/files/` |
| Username | Optional account name for HTTP basic authentication |
| Password | Optional password, stored as a secret |
| Signer name | The ENS name that signs, for example `laptop.alice.eth` |
| Signing key | The private key of the address the name resolves to, stored as a secret |
| Sepolia RPC address | The endpoint used to check signers against ENS, by default `https://ethereum-sepolia-rpc.publicnode.com` |
![The connection form](https://git.capsulizers.com/commons/memona-plugin-signature/raw/branch/main/images/connection-form.png)
| Field | Key | Meaning |
| --- | --- | --- |
| Server address | `url` | The folder's address, for example `https://dav.example.com/files/` |
| Username | `username` | Optional account name for HTTP basic authentication |
| Password | `password` | Optional password, stored as a secret |
| Signer name | `ensName` | The ENS name that signs, for example `laptop.alice.eth` |
| Signing key | `privateKey` | The private key of the address that owns the name, stored as a secret |
| Sepolia RPC address | `rpcUrl` | The endpoint used to check signers against ENS, by default `https://ethereum-sepolia-rpc.publicnode.com` |
| Trusted parent name | `trustedParent` | Optional. Only signers that are this name or one of its subnames count, for example `team.eth` |
The connection's allowed hosts must include the RPC address's host as well as
the server's, or every check reads as Sepolia unreachable.
Listing, reading, writing, creating directories, renaming and deleting behave
as in the WebDAV plugin: reads and writes stream in pieces of at most 1 MiB,
@@ -36,15 +42,44 @@ and the body's SHA-256, made with the configured key; other frontmatter and the
body stay byte for byte. A key that is not 32 bytes of hex refuses the
connection, and a `.md` file that is not UTF-8 refuses the save.
![A note saved in Memona, signed and verified](https://git.capsulizers.com/commons/memona-plugin-signature/raw/branch/main/images/after-save.png)
## Verifying
Reading a `.md` file of up to 40 KiB checks its signature against ENSv2 on
Sepolia through the RPC address and adds an `ens-verification` line to the
frontmatter Memona receives, which Memona shows as a badge; a larger one up to
1 MiB is marked as not checked. Both limits keep hashing and key recovery
inside the instruction budget Memona gives each call. The line never
reaches the server: a save drops it before signing, and one stored on the
server is replaced. Verdicts are reused for 30 seconds per signed body.
Reading a `.md` file checks its signature against ENSv2 on Sepolia and adds an
`ens-verification` line to the frontmatter Memona receives, which Memona shows
as a badge. The owner of the signer name comes from the Universal Resolver's
`findOwner`, so a name its parent revoked stops counting at once.
| Badge | Meaning |
| --- | --- |
| `Verified: bob.team.eth` | The name's current owner signed this exact body |
| `Tampered: signed as bob.team.eth` | The body changed after signing, or another key signed it |
| `Unauthorized: bob.team.eth is not registered` | The signature holds, but no one owns the name now: it was revoked or never granted |
| `Unauthorized: bob.team.eth is not a member of team.eth` | The signer is outside the trusted parent name |
| `Unsigned` | The file has no `signer` and `signature` |
| `Not checked: Sepolia unreachable` | The RPC address did not answer, so nothing was decided |
| `Not checked: file too large` | The file is over 40 KiB, too large to hash within one call |
| Verified | Tampered |
| --- | --- |
| ![Verified](https://git.capsulizers.com/commons/memona-plugin-signature/raw/branch/main/images/verified.png) | ![Tampered](https://git.capsulizers.com/commons/memona-plugin-signature/raw/branch/main/images/tampered.png) |
| Unauthorized | Unsigned |
| --- | --- |
| ![Unauthorized](https://git.capsulizers.com/commons/memona-plugin-signature/raw/branch/main/images/unauthorized.png) | ![Unsigned](https://git.capsulizers.com/commons/memona-plugin-signature/raw/branch/main/images/unsigned.png) |
The line never reaches the server: a save drops it before signing, and one
stored on the server is replaced, so a file cannot claim its own verdict.
Verdicts are reused for 30 seconds per signed body, a failed lookup included,
so an editor rereading a file does not flood the RPC. Stat, list and saves
keep reporting the stored size and the server's etag, so `If-Match` works as
before.
Memona gives each call into a plugin a fixed instruction budget, which is where
the size limits come from: checking hashes the body and recovers a key, so it
covers files up to 40 KiB; a file up to 1 MiB is marked not checked, and a
larger one streams through without a badge.
## Building