Skip to content

scheduler: Add CheckLightningAvailability feature gate - #741

Open
cdecker wants to merge 6 commits into
mainfrom
2028m08-app-show
Open

scheduler: Add CheckLightningAvailability feature gate#741
cdecker wants to merge 6 commits into
mainfrom
2028m08-app-show

Conversation

@cdecker

@cdecker cdecker commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Adds a feature gate that tells a downstream application whether it should
surface the Lightning account backed by a given node.

The answer belongs to Greenlight's Lightning Service Provider: it has either
granted that node a slot previously — grants are sticky — or has the capacity to
grant one now. Greenlight relays the question and keeps no state of its own.

New RPC on service Scheduler:

rpc CheckLightningAvailability(CheckLightningAvailabilityRequest)
    returns (CheckLightningAvailabilityResponse) {}

and, in the SDK:

lightningAvailable(nodeId: Data) throws -> Bool        // Swift
lightningAvailable(nodeId: ByteArray): Boolean         // Kotlin
lightning_available(node_id: bytes) -> bool            // Python

An application has to decide whether to offer Lightning before it creates a
node, so the call takes the node_id explicitly rather than deriving it from
credentials.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR

cdecker and others added 6 commits August 24, 2026 22:31
The target invoked a bare `python`, which is not on PATH here, so
regenerating the scheduler stubs failed with "No such file or
directory". The sibling gl-client-py Makefile already goes through
`uv run`; do the same.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR
Reports whether the Lightning account backed by a node_id may be
surfaced to the user, so an application that offers Lightning
alongside other account types can gate it. Greenlight relays the
question to its LSP, which answers based on whether it has previously
granted the node a slot, or has capacity to grant one now.

Unlike the other node-scoped calls this one is unauthenticated and
takes the node_id explicitly. An application has to decide whether to
offer Lightning *before* it creates a node, so at the time of asking
there is no node-bound certificate to derive the node from.

This commit only affects the protos and the generated files. Note that
the regenerated Python stubs carry unrelated churn from grpcio-tools
1.83 (the committed ones came from 1.78); the dependency is specified
as >=1.66 with no upper bound.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR
Sits in the unbounded `Scheduler<Creds>` impl alongside register and
recover, rather than the authenticated one: the call is meant to be
made before the node exists, so it must work on Nobody credentials and
cannot take the node_id from the credentials.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR
Exposes the gate to the bindings as `lightningAvailable(nodeId)` in
Swift and Kotlin, `lightning_available(node_id)` in Python. It goes on
the existing Scheduler object, which is already Nobody-only, so no
authenticated scheduler surface had to be introduced.

Regenerated bindings for Python, Kotlin and Swift. Ruby is left stale:
its backend rejects the SDK's callback interfaces ("No support for
coercing callback interfaces yet"), which predates this change. The
gl-sdk-swift package vendors its own copy of the Swift bindings and is
a separate repository, so it needs a sync of its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR
purerpc requires every method on the servicer, so this is needed for
any test to run once the proto lands, not just tests of the gate.

Defaults to unavailable, matching the real scheduler while no LSP is
wired up. Tests that need the other answer set `lightning_available`
on the fixture.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR
The protobuf gencode embeds a hard assertion that the runtime is at
least as new as the protoc that produced it. Regenerating with whatever
grpcio-tools the ambient venv happens to resolve therefore breaks every
consumer at import time as soon as the generator runs ahead of the
deployed runtime:

  VersionError: Detected incompatible Protobuf Gencode/Runtime versions
  when loading glclient/scheduler.proto: gencode 7.35.1 runtime 6.33.5

`grpcio-tools` was specified as >=1.66 and `protobuf` as >=6, both
without an upper bound, so the checked-in stubs silently depended on
who last regenerated them. This has broken CI three times.

Pin the generators and run them isolated from the project venv, so the
output is a function of the Makefile rather than of the developer's
machine, and cap the protobuf runtime below the next major so gencode
and runtime cannot drift apart again. mypy-protobuf is pinned too: it
generates the .pyi files and was contributing its own churn.

Regenerating now reproduces the previously committed files byte for
byte, so the diff is limited to the proto that actually changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6i275r245hhRHT1PvVKrR
@cdecker
cdecker enabled auto-merge (rebase) August 28, 2026 13:12
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