Skip to content

feat(tee-cli)!: assemble the founding validator set from the harvest - #91

Merged
samlaf merged 2 commits into
mainfrom
assemble-founding-validator-set
Aug 7, 2026
Merged

feat(tee-cli)!: assemble the founding validator set from the harvest#91
samlaf merged 2 commits into
mainfrom
assemble-founding-validator-set

Conversation

@samlaf

@samlaf samlaf commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

The founding reorder's assemble half: manifest assemble now derives the founding validator set from the harvested cohort instead of shipping the transitional empty set #87 left behind. With this the founding order is whole — init → up → harvest → assemble → configure — and network_id pins the founders' keys by construction.

What assemble does now

  • Pairs each harvested box (inputs/harvest/<node>.json) with an authored withdrawal-credentials address and the box's current IP from nodes/<node>.json, and emits the completed [[validators]] through summit genesis set-validators. The empty-set prepend is gone.
  • Re-verifies every archived quote against the policy compiled from inputs/measurements.json before pinning anything. This is the second of the two gates: root_key admission gates privacy, assemble-time DCAP gates consensus membership — summit never talks to the custodian, so an unverified founding pubkey could otherwise vote from outside a TEE.
  • Refuses a harvest carrying a repeated node or consensus pubkey: summit keys validator accounts by node pubkey, so a duplicate silently collapses the set, and a shared consensus key is accidental-equivocation material.

Withdrawal credentials are a list, not a node-name map

inputs/founder-withdrawal-credentials.json is now a JSON array of addresses, one per founding node, paired to the boxes in node-name order at assemble time. Keying it by cohort node name forced the file to be authored after up, which is backwards — the founders' addresses are a fact about the founders, not about the infrastructure. manifest init scaffolds it as the fourth authored input, and --founders N fills in 0x00…0<i> placeholders, which is all a throwaway founding needs.

The count check that replaces the exact name match runs twice: at harvest before any quote is fetched, and again at assemble. The pairing is positional and nothing downstream can tell a swapped pair from an intended one, so assemble logs each pairing as it builds the set.

up

  • --count is optional with --network: the authored credentials are the founding set, so they size the cohort. A contradicting --count is an error rather than a silent override.
  • The preflight image-pin check reads the authored inputs/measurements.json rather than the assembled manifest and policy. Provisioning precedes assembly now, so at up time the inputs are all a network directory holds. The success banner walks harvest → assemble → configure instead of pointing at the ceremony.

Renames, docs, and the throwaway path

  • measurement-policy.jsonmeasurement-policy-bootstrap.json: the file is only the founding allowlist — what bootstrap_policy_hash pins and registry genesis storage compiles from. The live policy is the registry contract's state, which the authority can mutate after genesis.
  • manifest init --force re-authors inputs for a re-found, matching the assemble --force that already existed.
  • tee/docs/runbook-devnet.md is the copy-pasteable throwaway recipe (init → provision → harvest → assemble → configure → smoke-test → down), and networks/.gitignore ignores tmp-*/ wholesale so a scratch founding never dirties git.
  • example-devnet is documented as a schema example, not a runnable founding: no artifact set can be assembled without a live harvest.
  • Every path the CLIs print is absolute, so it resolves from any cwd. The seismic_node Pulumi program path and its default stack config move to tee/cli/common/repo.py, letting manifest init point the founder at the stack config to review (vhd_blob_url, operator_ip_cidr) without common importing the network CLI.
  • The dev stack's vhd_blob_url moves to a 2026-08-07 image, built after the summit-key-holder unit landed (seismic-images feat(deploy_tee): open summit consensus port 18551 in the node NSG #48).

Breaking for any existing network directory: the policy filename and the credentials file shape both changed, and up --network now expects inputs/. Nothing is founded on the old layout.

Tests stay offline throughout (verifier subprocess and summit emitter mocked). Next: configure's per-boot IP splice, the launch-time pubkey and block-0 assertions, and deleting the genesis ceremony.

samlaf added 2 commits August 7, 2026 17:52
The founding reorder's assemble half: `manifest assemble` now derives the
founding validator set from the harvested cohort instead of shipping the
transitional empty set #87 left behind. With this the founding order is
whole — init → up → harvest → assemble → configure — and `network_id`
pins the founders' keys by construction.

## What assemble does now

- Pairs each harvested box (`inputs/harvest/<node>.json`) with an
authored withdrawal-credentials address and the box's current IP from
`nodes/<node>.json`, and emits the completed `[[validators]]` through
`summit genesis set-validators`. The empty-set prepend is gone.
- Re-verifies every archived quote against the policy compiled from
`inputs/measurements.json` before pinning anything. This is the second of
the two gates: root_key admission gates privacy, assemble-time DCAP gates
consensus membership — summit never talks to the custodian, so an
unverified founding pubkey could otherwise vote from outside a TEE.
- Refuses a harvest carrying a repeated node or consensus pubkey: summit
keys validator accounts by node pubkey, so a duplicate silently collapses
the set, and a shared consensus key is accidental-equivocation material.

## Withdrawal credentials are a list, not a node-name map

`inputs/founder-withdrawal-credentials.json` is now a JSON array of
addresses, one per founding node, paired to the boxes in node-name order
at assemble time. Keying it by cohort node name forced the file to be
authored after `up`, which is backwards — the founders' addresses are a
fact about the founders, not about the infrastructure. `manifest init`
scaffolds it as the fourth authored input, and `--founders N` fills in
`0x00…0<i>` placeholders, which is all a throwaway founding needs.

The count check that replaces the exact name match runs twice: at harvest
before any quote is fetched, and again at assemble. The pairing is
positional and nothing downstream can tell a swapped pair from an
intended one, so assemble logs each pairing as it builds the set.

## up

- `--count` is optional with `--network`: the authored credentials are
the founding set, so they size the cohort. A contradicting `--count` is
an error rather than a silent override.
- The preflight image-pin check reads the authored
`inputs/measurements.json` rather than the assembled manifest and policy.
Provisioning precedes assembly now, so at `up` time the inputs are all a
network directory holds. The success banner walks harvest → assemble →
configure instead of pointing at the ceremony.

## Renames, docs, and the throwaway path

- `measurement-policy.json` → `measurement-policy-bootstrap.json`: the
file is only the *founding* allowlist — what `bootstrap_policy_hash` pins
and registry genesis storage compiles from. The live policy is the
registry contract's state, which the authority can mutate after genesis.
- `manifest init --force` re-authors inputs for a re-found, matching the
`assemble --force` that already existed.
- `tee/docs/runbook-devnet.md` is the copy-pasteable throwaway recipe
(init → provision → harvest → assemble → configure → smoke-test → down),
and `networks/.gitignore` ignores `tmp-*/` wholesale so a scratch
founding never dirties git.
- `example-devnet` is documented as a schema example, not a runnable
founding: no artifact set can be assembled without a live harvest.
- Every path the CLIs print is absolute, so it resolves from any cwd. The
seismic_node Pulumi program path and its default stack config move to
`tee/cli/common/repo.py`, letting `manifest init` point the founder at
the stack config to review (vhd_blob_url, operator_ip_cidr) without
common importing the network CLI.
- The dev stack's `vhd_blob_url` moves to a 2026-08-07 image, built after
the summit-key-holder unit landed (seismic-images #48).

Breaking for any existing network directory: the policy filename and the
credentials file shape both changed, and `up --network` now expects
`inputs/`. Nothing is founded on the old layout.

Tests stay offline throughout (verifier subprocess and summit emitter
mocked). Next: configure's per-boot IP splice, the launch-time pubkey and
block-0 assertions, and deleting the genesis ceremony.
@samlaf
samlaf merged commit 57cdc87 into main Aug 7, 2026
2 checks passed
@samlaf
samlaf deleted the assemble-founding-validator-set branch August 7, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant