Repository navigation
Integrate connector ownership with Edge claims and independent expiry #976
Description
Parent: #970
Deliverable
A provider-side ownership adapter that uses foundation instance leases and per-prefix claims while enforcing one active MASQUE session per connector.
Dependencies
#972, #975; foundation #997 and #998 for integrated route/withdrawal evidence.
Galactic Edge integration (#992)
Implement this milestone as a consumer of the Galactic Edge provider contract. #992 owns provider authorization, host attachment lifecycle, shared-state fencing and maintenance, independently enforced forwarding expiry, prefix conflict arbitration/publication, and gVPC traffic policy. MASQUE owns client authentication, connector /96 assignment and retention, session packet checks, transport behavior and its provider adapter. Use the foundation's versioned contract and existing provider helpers; do not introduce a second host-networking controller, lease store or BGP publisher. Any required foundation change must be tracked and qualified under #992 before this milestone claims integrated acceptance.
Work
- Use the existing provider InstanceStore and route claim/release helpers with UID/resourceVersion preconditions, new process identity on restart and the contract timing parameters. Do not add a MASQUE host fence or parallel claim store.
- Treat a written claim as intent only: forwarding requires the accepted attachment/instance/route epoch and foundation readiness/gate state. Replacements obey closed-epoch confirmation or the contract takeover wait.
- Serialize same-instance connector sessions across both transports with an explicit session generation. Stop old packet I/O and discard old queued traffic before replacement activation; stale Close/release cannot affect a new session or claim.
- Implement Define connector admission, addressing and ownership contracts #972's connector-specific credential/revocation enforcement. Continued renewal for other connectors must not extend revoked session authority; any necessary foundation extension is an explicit prerequisite.
- Preserve independent foundation expiry while the provider, agent or API stalls. Release only the affected route on a single disconnect, preserving the instance lease and attachments used by other connectors.
Acceptance criteria
- Packet tests cover provider crash/pause, agent pause, API partition with client/VPC traffic still available, restart with cached authority, node container restart and cross-node replacement.
- Same-pod and cross-pod HTTP/3-to-HTTP/2 reconnects never have two forwarding sessions for one connector; delayed cleanup and buffered packets cannot affect the replacement.
- Measure local cutoff, local withdrawal and remote convergence separately against Define the internal provider contract #993 bounds/assumptions. Core controls gates and route withdrawal independently of session cancellation.
- Revoke or expire one connector while another keeps the shared instance renewing: the first stops within its documented bound and the other continues. Include stalled provider control handling and authority-source outage cases from Define connector admission, addressing and ownership contracts #972.
- Tests prove stale renewals, claim writes and release attempts cannot reopen expired authority or damage replacement routes; resolve CONNECT-IP server lacks overload limits and tenant isolation checks #991's unfenced-backend finding before exposure.
Scope follows #970: CONNECT-IP with HTTP/2 fallback; no public API development, plugin/portal integration, product-client development or production rollout.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
[-]MASQUE: enforce per-connector ownership and bounded local expiry[/-][+]Enforce per-connector ownership and bounded local expiry[/+][-]Enforce per-connector ownership and bounded local expiry[/-][+]Integrate connector ownership with Edge claims and independent expiry[/+]privateip commentedon Oct 27, 2026
Verdict: valid. The adapter from #975 still lacks the session ownership this issue asks for.
Checked on
mainat d2ef1ad:Admitrefuses a second request for the same connector with 503 while the first is open (internal/edge/masque/adapter.go,connectorOpen).TestDuplicateRequestasserts that refusal and passes. A reconnect on the same pod, including an HTTP/3 to HTTP/2 fallback, has to wait until the old stream closes. The adapter has no replacement path, no I/O barrier and no 1 s quiesce bound.Authorizerhas onlyAuthorize(internal/edge/masque/grant.go), and each session arms one timer atGrant.NotAfter. The adapter cannot refresh a grant or revoke one connector. Under the #972 contract, a grant lasts at most 30 s, so every session would end at that ceiling.validUntil(internal/edge/agent/gate.go), so one connector's revoked service closes only that connector's gate. This issue needs no foundation change.Already in place from #975: instance lease and route claims through
internal/edge/providerwith UID preconditions, admission gated on the accepted epoch, staleClosethat cannot release a successor's claim, and per-connector route release.Still open in other issues:
privateip commentedon Oct 27, 2026
Fix plan (approved):
Admitauthenticates a connector's new request before it touches the open one. It then ends the old session and waits up to 1 s for that session's packet I/O to stop and its lease to close. If the old session does not stop in time, the new request fails and the adapter retires the connector's authorization. The attachment and route references stay held during the handoff, so the claim is not released and taken again. Close and release calls compare the session ID, so a late call from the old session cannot affect its successor. A third request arriving during a handoff gets a retryable 503.AuthorizergainsRefreshandRetire, andAdaptergainsRevoke(connector). A refresh worker per session extends the session's deadline only when the refreshed grant keeps the same connector, VPC, service and /96. An unauthenticated or forbidden answer ends only that connector's session. When the authority is unavailable, the session keeps its last deadline and expires on it. The agent still closes the gate at the service'svalidUntil, so this does not replace the foundation ceiling.TUNBackend.Tests:
Not in this PR: the HTTP/2 rows (#981), cross-node replacement (needs #977's retire flow) and node reboot. The PR will reference this issue without closing it.
privateip commentedon Oct 27, 2026
#1162 merged. It adds same-pod connector replacement, per-connector grant refresh and revocation, and five ownership rows in the MASQUE lab suite. #1171 fixes two defects in those rows that their first run exposed.
At #1171's head, setup and all five rows pass in the lab:
Still open on this issue:
privateip commentedon Oct 29, 2026
Every acceptance criterion now has lab evidence, so I'm closing this. The adapter work merged in #1162 and #1171. The remaining rows merged in #1238 and #1240, and all of them passed on the containerlab lab at those PRs' heads.
One related bug stays open under #970: after an authority outage, the authority can renew a grant that core already expired (#1236). Authority still ends on time; the connector then gets 503 for about 30 s before it recovers.