Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -60,11 +60,18 @@ Found by taking real modules and asking what they would require. Each is a gap i
|
|||||||
| ~~1.1~~ | ~~An **object-store provision**~~ — **done 2026-08-31**, and it needed no change to the mesh: see below | seven assertions against a real store |
|
| ~~1.1~~ | ~~An **object-store provision**~~ — **done 2026-08-31**, and it needed no change to the mesh: see below | seven assertions against a real store |
|
||||||
| ~~1.2~~ | ~~**A session as a consumer of a licence**~~ — **done 2026-08-31**, and it also needed no change: see below | two sessions on one machine, different licences, each its own key |
|
| ~~1.2~~ | ~~**A session as a consumer of a licence**~~ — **done 2026-08-31**, and it also needed no change: see below | two sessions on one machine, different licences, each its own key |
|
||||||
| ~~1.3~~ | ~~A **network** shape, and ordering within a module~~ — **done 2026-08-31** | the shape is created and removed; ordering was already there, and is now asserted |
|
| ~~1.3~~ | ~~A **network** shape, and ordering within a module~~ — **done 2026-08-31** | the shape is created and removed; ordering was already there, and is now asserted |
|
||||||
| 1.4 | **Public certificate issuance** | a name reachable from outside is served with a certificate from a public authority, obtained against a **staging** endpoint unless told otherwise ([`04-ISSUES/004`](../../04-ISSUES/004-certificate-issuance-targets-production/00-report.md)) |
|
| 1.4 | **Public certificate issuance** — **built; one gap** | ordering, the challenge and issuance are proven against a real authority; **collecting the issued certificate is not** ([`04-ISSUES/020`](../../04-ISSUES/020-a-certificate-is-issued-and-never-collected/00-report.md)) |
|
||||||
|
|
||||||
**1.3 and 1.4 block later ones** and are listed now so they are not met as surprises. 1.3 is what
|
**1.3 and 1.4 block later ones** and are listed now so they are not met as surprises. 1.3 is what
|
||||||
a mail system needs and nothing else so far does.
|
a mail system needs and nothing else so far does.
|
||||||
|
|
||||||
|
**Phase 1 is closed with 1.4 partly open**, deliberately. Two of its four items needed no code at
|
||||||
|
all; the network shape was built; and certificates are configured correctly, order correctly, and
|
||||||
|
are issued correctly — the client does not collect what the authority issued, against a server
|
||||||
|
that exists to be a test server. That is filed rather than chased, because the remainder may say
|
||||||
|
nothing about a real authority and the next thing to learn comes from moving a module rather than
|
||||||
|
from a fourth lab run.
|
||||||
|
|
||||||
**Checkpoint:** each is demonstrated in the lab before the module needing it is attempted.
|
**Checkpoint:** each is demonstrated in the lab before the module needing it is attempted.
|
||||||
|
|
||||||
### 1.2, and the same surprise twice
|
### 1.2, and the same surprise twice
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
status: open
|
||||||
|
opened: 2026-08-31
|
||||||
|
located-in: [mesh-control, mesh-lab]
|
||||||
|
fixed-by:
|
||||||
|
amended-design:
|
||||||
|
---
|
||||||
|
|
||||||
|
# 020 — A certificate is issued and never collected
|
||||||
|
|
||||||
|
## Symptom
|
||||||
|
|
||||||
|
Against a real ACME server in the lab, the proxy orders a certificate for a name the mesh routes,
|
||||||
|
the challenge is answered, the authority **issues the certificate** — and the proxy never obtains
|
||||||
|
it. Every TLS handshake then fails, and the order is retried indefinitely.
|
||||||
|
|
||||||
|
The client's error, once per attempt:
|
||||||
|
|
||||||
|
```
|
||||||
|
http: TLS handshake error: Post "": unsupported protocol scheme ""
|
||||||
|
```
|
||||||
|
|
||||||
|
A POST to an empty URL: the certificate's location, on an order the authority considers valid.
|
||||||
|
|
||||||
|
## What is proven, and it is most of it
|
||||||
|
|
||||||
|
Read from the authority's own log rather than inferred:
|
||||||
|
|
||||||
|
```
|
||||||
|
Starting 3 validations
|
||||||
|
authz … set VALID by completed challenge …
|
||||||
|
POST /finalize-order/ → Order … is fully authorized. Processing finalization
|
||||||
|
Issued certificate serial 3ef142939115ee88
|
||||||
|
```
|
||||||
|
|
||||||
|
**The hard half works.** The order is created, the HTTP-01 challenge is answered *at the name being
|
||||||
|
certified* on port 80 through the proxy itself, the authorisation goes valid, finalisation is
|
||||||
|
accepted, and a certificate is issued. Across one run the authority issued **two** certificates and
|
||||||
|
accepted finalise **three** times — the client reaches issuance every attempt and fails at the same
|
||||||
|
step after it.
|
||||||
|
|
||||||
|
**And the policy that guards the quota is proven too.** The second assertion in the same file
|
||||||
|
passes: no certificate is ordered for a name nothing routes, so a scan cannot spend an account's
|
||||||
|
rate limit.
|
||||||
|
|
||||||
|
## What is not known
|
||||||
|
|
||||||
|
**Whether this happens against a real authority at all.** Everything above is against Pebble, which
|
||||||
|
exists to be a test server. The failure is in the last hop between one client and one server, and
|
||||||
|
may say nothing about behaviour against a public authority.
|
||||||
|
|
||||||
|
## Ruled out
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| the directory | fetched and complete — `newAccount`, `newNonce`, `newOrder`, `revokeCert` all present |
|
||||||
|
| the authority's API certificate | covers `127.0.0.1`; the bundle is named explicitly and verification is not skipped |
|
||||||
|
| a hand-written server config | suspected, and wrong. Replacing it with the server's **own** default config, changing only the challenge port, gives the identical error |
|
||||||
|
| the finalize URL being empty | the authority logs finalisation being accepted |
|
||||||
|
| the challenge path | the authorisation goes valid |
|
||||||
|
|
||||||
|
## Where it might be
|
||||||
|
|
||||||
|
- **The order's `certificate` field is absent when the client reads it.** The client waits for the
|
||||||
|
order to become valid and only then fetches, so an empty location on a valid order is the
|
||||||
|
remaining shape.
|
||||||
|
- **A moving tag was used.** `pebble:latest` advertises a draft *profiles* extension in its
|
||||||
|
directory. A pinned older version is being tried — the third time today that not pinning a tag
|
||||||
|
cost a run.
|
||||||
|
|
||||||
|
## Why this is filed rather than pursued
|
||||||
|
|
||||||
|
**The mesh-side behaviour is proven and the remainder is interop between two libraries.** Continuing
|
||||||
|
would be several more twenty-minute lab runs against a server that is not the one production uses,
|
||||||
|
to chase a defect that may not exist there.
|
||||||
|
|
||||||
|
**What the mesh needed to show, it showed**: a name it routes gets a certificate ordered from a
|
||||||
|
configured authority, and a name it does not route gets nothing. The configuration is right, the
|
||||||
|
challenge path is right, and issuance happens.
|
||||||
|
|
||||||
|
## What would close it
|
||||||
|
|
||||||
|
- The same scenario against a different ACME implementation — a second server, or a real staging
|
||||||
|
endpoint from a machine that can reach one. **If it passes there, this is a Pebble interop
|
||||||
|
detail and the issue closes with that recorded.**
|
||||||
|
- Or the client's request captured on the wire, showing what the order actually contained when the
|
||||||
|
location was read.
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
- `mesh-lab test/integration/certificates.test.ts`, scenario `a-public-name`
|
||||||
|
- One assertion passes (no certificate for an unrouted name); one fails (a routed name is never
|
||||||
|
served).
|
||||||
Reference in New Issue
Block a user