Skip to content

Gateway readiness trusts prepared-only PF state and holds the mutation lock for 60 seconds #305

Description

@munezaclovis

Summary

Gateway readiness switches from the Gateway's high backend ports to public ports 80/443 when either active PF redirects match or merely the prepared anchor file matches. If macOS has removed PV's system pf.conf reference, the prepared file still matches even though no redirect is active.

Reconciliation then probes unreachable public ports for 60 seconds, marks a healthy Gateway process failed, and holds the global mutation lock for the duration.

This compounded the live incident described in #300's follow-up investigation.

Current behavior

The relevant selection is in gateway_readiness_ports:

if active_gateway_redirects_match_plan(plan)
    || prepared_gateway_redirects_match_plan(paths, plan)
{
    return GatewayReadinessPorts {
        http: PUBLIC_HTTP_PORT,
        https: PUBLIC_HTTPS_PORT,
    };
}

The reconciliation queue acquires the shared lock when mutating work is enqueued (reconciliation.rs) and releases it only when the queue becomes idle.

Observed sequence:

  1. Prepared anchor correctly mapped 80 → 48080 and 443 → 48443.
  2. The system anchor file also existed, but the system pf.conf reference was missing.
  3. Gateway and Project worker processes were listening and direct high-port HTTPS returned 200.
  4. Reconciliation selected ports 80/443 solely because the prepared file matched.
  5. The public probe timed out after 60 seconds with connection refused.
  6. During that minute, pv update --check reported that the update lock was held.

This also conflicts with the documented readiness example that the Gateway responds on its high HTTP/HTTPS ports (DESIGN.md).

Expected behavior

Prepared configuration alone must not be treated as proof that privileged redirects are loaded. Gateway process readiness and low-port system-integration health should remain distinguishable.

Acceptance criteria

  • A current prepared anchor with a missing/stale system reference does not select a doomed public-port readiness probe.
  • A live Gateway on its assigned high ports is not marked failed solely because privileged PF routing is stale.
  • PF drift is recorded/reported as a system-integration repair requirement.
  • Reconciliation does not hold the global mutation lock for the full public-port timeout in this state.
  • Preserve safe handling for the macOS behavior noted in the code comment where direct target-port connections can hang while matching redirects are genuinely active.
  • Add integration coverage for:
    • prepared current + system reference missing + backend healthy;
    • active redirects current;
    • backend genuinely unhealthy.
  • Do not change the foreground privilege boundary for pv ports:install.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcontrol-planeControl-plane architecturegatewayGateway, DNS, TLS, pv openpriority-highP1 high priorityready-for-agentFully specified, ready for an AFK agentvalue-highHigh value

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions