Problem
With app installs (#359, #400), an appId is the manifest's own claim. Any key can present a manifest under com.example.notes:
- Where that app isn't installed, approving the manifest gives the key the app's families.
- Where it is installed, approving it links the key to the existing install. The key then holds the app's grants and may migrate its types, and the manifest's
requests replace those of every key already linked.
Today the plan's newKey and linkedKeys show this, so the owner's review is the only check. apps.md § Who owns a family states this residual risk.
A design that was prototyped and taken out of #400
Commits 07ad8e8, e1232a7 and de4e587 on #400's branch implemented these pieces:
- Signed manifests. A
publisher DID signs canonical JSON (manifestPayload() / signManifest()).
- Publisher pinning. A manifest under the same
appId from any other publisher is refused while the install is live. After an uninstall, a new publisher may take the install up (publisherChanged), which unlinks the old keys.
- Forward-only
release. This stops an older signed manifest being replayed over a newer install.
- Optional certified keys (
certifyKey()). There is also a sticky keysCertified flag: once one key is certified, a new key must be too.
did:web publishers. They are verified through a verifyPublisher callback, and namespaceVerified is set when the domain, reversed, is the appId.
It was taken out because:
- It's mostly trust on first use anyway. With a
did:key publisher, the first manifest a stack sees under an appId gets pinned, whoever signed it.
- Certificates prove less than they seem to. For an app on users' devices, a certificate proves only what the publisher's issuing service checked, which may be nothing.
- Each layer added edge cases: the sticky flag surviving an uninstall, publisher rotation unlinking keys, and releases not carrying across a publisher change.
- It overlaps
identity.md § Deferred: key rotation. Tying a key to an identity that outlives it is the same problem.
- It makes the simplest case heavier. Every app, including an in-process one, would need a publisher keypair.
Questions
- Should this be designed together with key rotation, for example a stack-hosted DID method or a signed hand-off log?
- Is
did:web with a domain matching the appId the only case worth proving, with everything else left to owner review?
- What should the plan show the owner so it's meaningful without signatures, for example a fingerprint of the key and where else it is installed?
- Does upgrade protection (no other key can upgrade a live install) need signatures at all, or would pinning to the first linked key, with the owner approving every new key, be enough?
Problem
With app installs (#359, #400), an
appIdis the manifest's own claim. Any key can present a manifest undercom.example.notes:requestsreplace those of every key already linked.Today the plan's
newKeyandlinkedKeysshow this, so the owner's review is the only check.apps.md § Who owns a familystates this residual risk.A design that was prototyped and taken out of #400
Commits
07ad8e8,e1232a7andde4e587on #400's branch implemented these pieces:publisherDID signs canonical JSON (manifestPayload()/signManifest()).appIdfrom any other publisher is refused while the install is live. After an uninstall, a new publisher may take the install up (publisherChanged), which unlinks the old keys.release. This stops an older signed manifest being replayed over a newer install.certifyKey()). There is also a stickykeysCertifiedflag: once one key is certified, a new key must be too.did:webpublishers. They are verified through averifyPublishercallback, andnamespaceVerifiedis set when the domain, reversed, is theappId.It was taken out because:
did:keypublisher, the first manifest a stack sees under anappIdgets pinned, whoever signed it.identity.md § Deferred: key rotation. Tying a key to an identity that outlives it is the same problem.Questions
did:webwith a domain matching theappIdthe only case worth proving, with everything else left to owner review?