Aether trust standard
What the badges mean, and what we actually check
Every listing in the Aether catalog carries a trust tier and a signed report. Nothing here is a marketing label: each tier maps to specific evidence, and each scan records the exact checks that produced its score. Reports are HMAC-signed with a versioned key so anyone can re-verify them later.
Trust tiers
Submitted, not yet public.
- · A draft or pending submission exists
- · Domain ownership not yet proven
- · Not discoverable in the public catalog
Origin verified, automated scan passed.
- · DNS or HTML domain ownership proof accepted
- · Every blocking check passed on the live release
- · Signed trust report published on the listing
Publisher entity verified on top of the origin.
- · Everything at Listed
- · Publisher identity or organisation confirmed
- · Clean scan history across consecutive releases
Human review of capabilities and data flows.
- · Everything at Verified
- · Manual review of the capability manifest and agent policy
- · Re-review required on any capability expansion
The checks
Blocking checks must pass for a listing to stay public. Non-blocking checks affect the score and the tier ceiling.
Origin & ownership
The declared start URL uses https:// and resolves without falling back to plaintext.
Installed web apps hold credentials and tokens. Plaintext transport makes every other guarantee meaningless.
check id: httpsA DNS TXT record or a token file at /.well-known on the declared domain proves the publisher controls the origin.
Everything downstream — badges, reports, delisting — is keyed to an origin somebody actually owns.
check id: domain-ownershipThe start URL returns a 2xx response within the scan timeout.
Dead listings erode catalog trust faster than bad ones.
check id: reachableSecurity posture
Checks for Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, and frame protections.
These headers are the cheapest available defence against injection and clickjacking of an installed surface.
check id: security-headersEnumerates external script origins loaded by the start URL and flags unexpected trackers.
Publishers should be able to name every origin that executes inside their app.
check id: third-partyPWA installability
A linked manifest with name, start_url, display, and theme_color.
Without it there is no Add to Home Screen, and no store-equivalent install experience.
check id: manifestIcons at the sizes iOS and Android require for a home-screen launch.
A blurry or missing icon is the single most common reason an install feels untrustworthy.
check id: manifest-iconsA service worker is registered from the start URL scope.
Offline resilience is the functional parity claim PWAs make against native store apps.
check id: service-workerPermissions & capabilities
Sensitive browser APIs detected in the page — geolocation, camera, microphone, clipboard, notifications — are compared against the capabilities the publisher declared.
Undeclared capability use is the failure mode app stores exist to catch.
check id: permissions-declaredAgent & prompt policy
Agent listings declare the tools, data sources, and side effects they can invoke.
An agent without a capability manifest cannot be reasoned about by anyone, including its own users.
check id: capability-manifestThe declared autonomy level (assistive, supervised, autonomous) is consistent with the declared capabilities.
An agent that writes to production systems cannot be labelled assistive.
check id: autonomy-labelRetention, model-training use, and third-party sharing are disclosed in structured form.
Structured disclosure is what makes catalog-wide compliance filtering possible.
check id: data-practicesA reachable privacy or usage policy is linked from the app itself.
Users deserve a durable, publisher-owned statement, not just our summary of it.
check id: policy-linkVerifying a report yourself
Every listing detail page exposes its signature and a one-click verification. Signatures are versioned — v2:sha256:… — so reports signed with a retired key still verify, and the response tells you whether the key that signed it is still active.
GET /api/public/verify-report?scanId=<scan-id>
{ "valid": true, "keyId": "v2", "rotated": false,
"app": "…", "score": 94, "verdict": "pass" }