Repository navigation
Description
Part of #173 and the first goal in #89.
Installed Homes trust one publisher key. publisher_dids is a list (elastos/crates/elastos-server/src/sources.rs:48), but head verification and discovery use only its first entry (elastos/crates/elastos-server/src/update.rs:92-96, 578; sources.rs:269, 296, 377), and the discovery URI is derived from the signer DID (elastos/crates/elastos-server/src/publish.rs:83-88). There is no signed hand-over, so every key change forces all installs to re-trust by hand, as #186 does now. This issue builds the foundation so a future key change needs no reinstall.
Design (close to TUF's root and targets roles, kept minimal):
- A root key, used rarely and kept the safest, is what installs pin. install.sh carries the root DID, and discovery derives from the root DID. The key created on 2 October (Replace the maintainer release key and keep signing off the public server #186) becomes this root, so installs made during G1 Install and update: Signed update #89's M1 and M2 already pin it.
- The root signs a versioned publisher-keys statement naming the current release signing key or keys. Releases are signed by a listed key. Clients fetch the statement with the head, accept a release only from a listed key, and keep the highest statement version they have seen.
- Rotating or revoking a signing key is a new statement signed by the root; installs follow without user action.
- Rotating the root needs a statement signed by both the old and the new root. If the old root is compromised, the user re-trusts explicitly.
Status (3 Oct): draft PR #221 holds the first signer code only: publisher-keys statement custody with one root signature. It activates nothing. Client admission, root handover, publish and install integration, and the #157 freshness contract remain open; public activation waits for #89's update-client admission.
Done means
- Releases are signed by a delegated signing key, separate from the root, named in a root-signed publisher-keys statement. Test: a fresh install pins only the root DID and accepts such a release.
- Signing-key rotation: a release signed by a newly listed key is accepted with no user action; one signed by a revoked or unlisted key is refused; a statement with a lower version than one already seen is refused. Tests.
- Root rotation: a statement signed by both the old and the new root moves trust to the new root; a statement signed by only one of them is refused. Tests. The explicit re-trust path for a compromised root is documented and tested.
- Expiry and freshness use the one contract agreed in Design signed release-head freshness and explicit gateway freeze reporting #157 (lifetime, clock skew, renewal, legacy heads); this issue does not define its own. An expired statement is never accepted as current, clock skew is bounded, offline clients report "freshness unknown" instead of accepting stale metadata. Tests.
- The publish tooling creates and signs statements; the root key is used only for statements, never for releases.
- G1 Install and update: Signed update #89's M1 and M2 are repeated under this structure before M3.
Later, once independent custody exists: a threshold of root keys, and a committed pre-rotation chain for the root.
Activity
andersalm commentedon Oct 3, 2026
Release work starts with the strict publisher-keys statement and custody roles; public activation waits for the matching update-client admission in #89. The current M1/M2 signing flow remains the accepted first hop.
Proposed statement:
elastos.publisher-keys/v1, fieldsversion,channel,root_did,previous_root_did,issued_at,expires_at,release_dids; signature domainelastos.publisher.keys.v1. Distinct, bounded delegates exclude both roots; one root signs delegation, both old and new roots sign one identical handover payload.Carry the statement inside a new signed release-head schema/domain on the existing filename and Carrier path. A separate delegate signs the head/release; discovery follows the root, with the old discovery path retained through a handover. Transport holder, node and ticket remain separate.
Clients retain the highest statement version/digest and a separate head revision/digest, accept equal versions only for identical bytes, and commit valid revocations before later artifact admission. Explicit re-trust resets delegation deliberately and preserves configured transport; lower, expired, unlisted, revoked and single-signature cases preserve the installed release.
Decision needed under #157/#89: agree statement/head lifetime, future-issue skew, renewal cadence, root-handover reachability and the persistent client-state interface before activation. Tests will cover malformed/duplicate fields, role separation, rollback/equivocation, expiry/offline freshness unknown and dual-root continuity; real separate custody and repeated M1/M2 remain operator proof.
andersalm commentedon Oct 3, 2026
The first signer code part is preserved in draft PR221, targeting develop; local and remote match.
Trusted custody roles separate publisher-keys statements from release manifests; strict hashes, domains, roots/delegates and explicit time/version policy bounds keep candidate input as data. Empty delegates revoke all release keys.
All 49 signer tests and the existing CI entry point passed, with independent development PASS and the basic entropy/format/diff gate.
The draft emits one root signature only. Client admission, complete root handover, publish/install integration and the #157 freshness contract remain open; the current approved M1/M2 flow stays available.
Resume from this draft after the release/update contract is agreed; different-family adversarial PASS and all Done means are required before final acceptance.
andersalm commentedon Oct 3, 2026
The signer correction is pushed to draft PR221; local and remote match after a normal merge of accepted develop.
Both custody roles retain canary/develop and stable/main-tag source admission; a stable statement from develop without its main tag is refused before backend creation.
All 50 signer tests and the basic gate passed, with current independent development PASS; renewed CI is green, including Runtime/browser, capsules and all three installed platform checks.
The draft retains one-root-signature scope and waits for the release/update contract decision. Client admission, dual-root handover, publish/install integration and the #157 freshness decision remain open.
Resume after that contract is agreed; the different-family adversarial review and complete installed acceptance remain gates.
andersalm commentedon Oct 10, 2026
Moved to After 0.8.0: not in the install/update list for 0.8.0 (#89 Remaining for 0.8.0).
andersalm commentedon Nov 4, 2026
Part of the publishing parent issue #525 (anyone can run a marketplace; ElastOS-signed ones are trusted by default).