Skip to content

SW-Serverless 10.2.0: Python and Node adapters, sw-serverless CLI, standalone from Bitween - #166

Merged
samerzughul merged 17 commits into
mainfrom
release/10.2.0
Oct 10, 2026
Merged

samerzughul merged 17 commits into
mainfrom
release/10.2.0

Conversation

@samerzughul

Copy link
Copy Markdown
Member

What's in 10.2.0

  • Python and Node/TypeScript adapters. Zero-dependency SDKs sw-serverless (PyPI) and @simplyworks/sw-serverless (npm), run by the host over gRPC on a Unix domain socket, as classic or resident adapters. Tested through the real host.
  • The sw-serverless CLI. It scaffolds, builds, tests, runs and publishes adapters in .NET, Python and Node. It is released on GitHub as self-contained binaries (Linux x64/arm64, glibc and musl; macOS; Windows), with SHA256SUMS, by .github/workflows/cli-release.yml on a cli-v<version> tag.
  • Independent of Bitween. Nothing in SW-Serverless names Bitween any more. An application brings its own contract (ContractDocument), templates and vendored packages through SimplyWorks.Serverless.Tooling. The manifest's compatibility.applications replaces minBitweenVersion, which is still read.
  • Fixes:
    • Resident start hooks run beside the read loop, so a slow start no longer stalls the handshake. Commands and shutdown wait for start.
    • A host with resident adapters only can start without AddServerless.
    • .NET adapters can be described from a single-file sw-serverless.
    • gRPC sessions whose values include nulls now start.
  • Docs. README and docs/ describe SW-Serverless on its own.

Compatibility

Backward compatible: existing .NET adapters, packages and manifests keep working. A Python or Node adapter is published to versions and the catalog only, so hosts older than 10.1 never see it.

Tests

Compatibility 29, Installer 131 and Unit 169 pass, plus the Python and Node SDK tests.

After merge

Publish the 10.2.0 NuGet packages. Bitween's releases/r10.0-staging depends on them. PyPI/npm publishing and the first cli-v tag come later.

Commits

  • Add the Python SDK
  • Run Python adapters through the real host in the tests
  • Build, scaffold, test and run Python adapters with the CLI
  • Start gRPC sessions whose values include nulls
  • Add the Node SDK
  • Run Node adapters through the real host in the tests
  • Build, scaffold, test and run Node adapters with the CLI
  • Publish and promote under the adapters folder a deployment uses
  • Take Bitween out of SW-Serverless; the CLI becomes sw-serverless
  • Resolve storage flags in Tooling, for any CLI built on it
  • Describe .NET adapters from a single-file sw-serverless
  • Release sw-serverless as self-contained binaries on GitHub
  • Start resident adapters beside the read loop, in every SDK
  • Let a host with resident adapters only start without AddServerless
  • Fix what the docs review found, and drop names that aren't ours
  • Document SW-Serverless on its own
  • Release sw-serverless for musl Linux on arm64 too

Adapters in Python 3.12+ declare settings with sw.expect, mark commands with
@sw.command, and run with sw.run, which serves --describe and otherwise the
host that started it. Resident adapters add start, stop, status and reset;
a call's context publishes events, keeps state and records metrics, and
Python logging reaches the host.

It has no dependencies. The protocol is one gRPC stream over a Unix socket,
so the SDK carries its own protobuf codec for adapter.proto's messages and a
small HTTP/2 client with HPACK and flow control in both directions. It
vendors into a package as plain files, for any platform, with nothing to
fetch.
Classic sessions as Bitween runs handlers, a resident instance with status,
events, state, reset and drain, payloads well past the HTTP/2 window both
ways, errors with their types, a cancelled call, concurrent calls on one
instance, --describe, and the Bitween handler, validator and receiver
written with simplyworks-bitween.
serverless init --lang python writes a working adapter of any Bitween kind.
serverless build packages a Python adapter: its files as they are, the SDK
and the Bitween kinds vendored from copies the CLI carries, requirements.txt
vendored with pip, and an entry that puts them on the path. Pure-Python
requirements are vendored once and the package runs anywhere; native ones
are vendored per target platform, linux-x64 and linux-arm64 unless
adapter.json names others, and the manifest lists them. The adapter
describes itself on the build machine, with its requirements installed
there only for that when it isn't a target.

test and run build a Python project folder first, as a .NET one. Scaffolded
files end in a newline.
A protobuf map can't hold a null, and Ready's startup values were copied in
as given: Bitween's gateway runs validators with no correlation id, so any
gRPC adapter used as a validator there failed before it was ready, its
stream ended by an exception in Attach. Null values are left out, and read
as absent, which is what null meant.
Adapters in JavaScript or TypeScript on Node 22+ declare settings with
expect, commands in a static commands map with how each argument and result
is encoded, and run with run(), which serves --describe and otherwise the
host that started it. Resident adapters add start, stop, status and reset;
a call's context publishes events, keeps state, records metrics and has a
signal that aborts when the host gives up on the call; logs reach the host.

No dependencies: Node's http2 carries the gRPC stream and the SDK its own
protobuf codec, whose bytes match the Python SDK's. Typings ship with it.
The same ground as the Python tests, with the adapters built by serverless
build: classic sessions, a resident instance, large payloads both ways,
errors, a cancelled call, concurrent calls, and the Bitween handler and
receiver in JavaScript and validator in TypeScript. Tests needing Node to
strip TypeScript types are inconclusive on a Node older than 22.13.
serverless init --lang node or typescript writes a working adapter of any
Bitween kind; the TypeScript one is an ES module checked by tsc --noEmit.
serverless build packages it: its files as they are, TypeScript turned into
JavaScript by Node's own type stripping, so no compiler is needed and syntax
that would need compiling is refused; the SDK and Bitween kinds vendored
into node_modules from copies the CLI carries; and package.json's other
dependencies installed by npm without running their scripts. A dependency
with native code is refused unless the adapter is limited to the platform
it is built on. test and run build a Node project folder first.
AdapterRepository and the package publish took the adapters folder to be
"adapters" always, while hosts are configured with their own. Both now
take it, defaulting to "adapters", so Bitween can publish where its hosts
read; the static members stay as they were.
SW-Serverless knew one application by name: its CLI scaffolded Bitween's
kinds, vendored Bitween's Python and Node packages into every build and
carried Bitween's contract in its conformance kit, and its manifest had a
minBitweenVersion. None of it belongs to a library any application can use.

- The CLI is sw-serverless. init writes a generic adapter — two settings,
  two commands — in .NET, Python, JavaScript or TypeScript.
- The kit carries no contract. One is handed to it with --contract or
  ConformanceOptions.Contracts, or registered once by an application's own
  tool (ContractDocument.Register, FromJson).
- The build vendors only the SDK; an application hands it its own packages
  (BuildRequest.Packages), which requirements.txt and package.json may then
  name without being fetched.
- The scaffolder takes an application's templates (Scaffold with Templates)
  and keeps its checks and layout.
- compatibility.applications gives each application's minimum version;
  manifests written with minBitweenVersion stay readable through
  MinVersionOf("bitween").
- The Python and Node SDKs are sw-serverless (import sw_serverless) and
  @simplyworks/sw-serverless, 10.2.0. Python gains sw.implements to declare
  a contract and its kinds.
- Tests use a sample "orders" contract of their own, and nothing reads
  ../Bitween-api. The release is 10.2.0: public members were removed.
Where an adapter is published — flags, then the -c file, then SWSL_*
variables — was worked out in the sw-serverless project, so a CLI built on
Tooling had to copy it. It is StorageResolver and StorageFlags in Tooling
now; the command line's resolver delegates to it.
A self-contained single-file build has no runtime assemblies on disk, so the
older publish form read an adapter's types against nothing and took every
adapter for a classic one with no kinds. It now reads them against an
installed .NET when its own runtime has no files: DOTNET_ROOT, the usual
folders, or what dotnet --list-runtimes reports. A .NET adapter needs one
to run anyway.
A tag cli-v<version> builds the command for Linux (x64, arm64, musl x64),
macOS (x64, arm64) and Windows (x64), single-file and self-contained, and
publishes them on a release with SHA256SUMS. scripts/install-cli.sh
installs the latest, checking it against the checksums.
Start was awaited inside the loop that reads the host's frames, so a start
that asked the host for anything — its state, an event's ack — waited for an
answer that loop could never read, and the adapter hung. Start now runs
beside it: commands wait until it has returned, a stop waits for it within
its own deadline, and a start that fails stops the adapter as before. The
Python and Node test residents now read and write state from start.
The default locator took the installer when it was built, which needs
ServerlessOptions and storage, so a host giving every adapter by path could
not start. It takes the installer only when it installs from storage, and
says what is missing then.
- Manifests no longer carry isResident, which is worked out from lifecycle.
- A package's Lang metadata is its runtime, not always dotnet.
- test says when a contract file can't be read, instead of crashing.
- --allow and --contract say they take several values separated by spaces.
- musl platforms are no longer offered for Python builds, which manifests
  and hosts don't recognise.
- Comments no longer cite a design document this repository doesn't have,
  or name other products; InternalsVisibleTo names sw-serverless and the
  packages point at this repository.
A README and docs written for anyone building a host or an adapter, with no
particular application in mind: concepts, hosting, writing adapters in .NET,
Python and Node, the sw-serverless CLI, the manifest, packaging and storage,
contracts and the conformance kit, the protocol, extending the tooling with
an application's own CLI, and compatibility. Installing the CLI from its
GitHub releases. The resident adapters design, written for one application,
moves to that application's repository.
@coderabbitai

coderabbitai Bot commented Oct 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 134 files, which is 34 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration
  • Configuration used: Repository: simplify9/coderabbit/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 406b93f5-ceae-408b-867d-089ee3bb7016

📥 Commits

Reviewing files that changed from the base of the PR and between e0802f1 and c487ff8.


📒 Files selected for processing (134)
  • .github/workflows/cli-release.yml
  • .github/workflows/node-sdk.yml
  • .github/workflows/nuget-publish.yml
  • .github/workflows/pr.yml
  • .github/workflows/python-sdk.yml
  • README.md
  • SW.Serverless.Compat.ManifestV1002/SW.Serverless.Compat.ManifestV1002.csproj
  • SW.Serverless.CompatibilityTests/ListingAndManifestTests.cs
  • SW.Serverless.CompatibilityTests/MultiLanguageManifestTests.cs
  • SW.Serverless.CompatibilityTests/PackageLayoutTests.cs
  • SW.Serverless.CompatibilityTests/SW.Serverless.CompatibilityTests.csproj
  • SW.Serverless.Contract/Catalog/AdapterManifest.cs
  • SW.Serverless.Contract/Protos/adapter.proto
  • SW.Serverless.Contract/SW.Serverless.Contract.csproj
  • SW.Serverless.Installer.UnitTests/BuildTests.cs
  • SW.Serverless.Installer.UnitTests/CatalogPublishingTests.cs
  • SW.Serverless.Installer.UnitTests/CliCommandTests.cs
  • SW.Serverless.Installer.UnitTests/ConformanceTests.cs
  • SW.Serverless.Installer.UnitTests/Contracts/order.schema.json
  • SW.Serverless.Installer.UnitTests/Contracts/orders-adapter-contract.v1.json
  • SW.Serverless.Installer.UnitTests/Contracts/receipt.schema.json
  • SW.Serverless.Installer.UnitTests/SW.Serverless.Installer.UnitTests.csproj
  • SW.Serverless.Installer/AdapterCommands.cs
  • SW.Serverless.Installer/Options.cs
  • SW.Serverless.Installer/Program.cs
  • SW.Serverless.Installer/SW.Serverless.Installer.csproj
  • SW.Serverless.Installer/UploadOptionsResolver.cs
  • SW.Serverless.SampleWeb/Telemetry/DashboardEventSink.cs
  • SW.Serverless.SampleWeb/Telemetry/DedupeWindow.cs
  • SW.Serverless.Samples.Carrier/CallLog.cs
  • SW.Serverless.Samples.Carrier/CarrierHandler.cs
  • SW.Serverless.Samples.Carrier/CarrierOptions.cs
  • SW.Serverless.Samples.Carrier/Contracts.cs
  • SW.Serverless.Samples.CarrierContract/Protos/carrier.proto
  • SW.Serverless.Samples.Classic/Handler.cs
  • SW.Serverless.Samples.FolderSource/Handler.cs
  • SW.Serverless.Samples.Host/ConsoleEventSink.cs
  • SW.Serverless.Samples.Host/Program.cs
  • SW.Serverless.Samples.RabbitMq/Publisher/PublisherHandler.cs
  • SW.Serverless.Sdk/AdapterContractAttribute.cs
  • SW.Serverless.Sdk/Resident/AdapterStatus.cs
  • SW.Serverless.Sdk/Resident/Handshake.cs
  • SW.Serverless.Sdk/Resident/IAdapterContext.cs
  • SW.Serverless.Sdk/Resident/IResidentAdapter.cs
  • SW.Serverless.Sdk/Resident/ResidentRunner.cs
  • SW.Serverless.Sdk/Runner.cs
  • SW.Serverless.Sdk/SW.Serverless.Sdk.csproj
  • SW.Serverless.Tooling/AdapterDescriber.cs
  • SW.Serverless.Tooling/AdapterRepository.cs
  • SW.Serverless.Tooling/Building/NodeBuild.cs
  • SW.Serverless.Tooling/Building/PackageBuilder.cs
  • SW.Serverless.Tooling/Building/PythonBuild.cs
  • SW.Serverless.Tooling/CloudFilesFactory.cs
  • SW.Serverless.Tooling/Conformance/ConformanceRunner.cs
  • SW.Serverless.Tooling/Conformance/ContractDocument.cs
  • SW.Serverless.Tooling/Contracts/bitween/bitween-adapter-contract.v1.json
  • SW.Serverless.Tooling/Contracts/bitween/exchange-file.schema.json
  • SW.Serverless.Tooling/Contracts/bitween/validation-result.schema.json
  • SW.Serverless.Tooling/LocalAdapterHost.cs
  • SW.Serverless.Tooling/PackagePublisher.cs
  • SW.Serverless.Tooling/SW.Serverless.Tooling.csproj
  • SW.Serverless.Tooling/Scaffolding/Scaffolder.cs
  • SW.Serverless.Tooling/StorageResolver.cs
  • SW.Serverless.UnitTests.BitweenHandler/Program.cs
  • SW.Serverless.UnitTests.BitweenReceiver/Program.cs
  • SW.Serverless.UnitTests.GrpcClassicAdapter/Program.cs
  • SW.Serverless.UnitTests.OrdersProcessor/Program.cs
  • SW.Serverless.UnitTests.OrdersProcessor/SW.Serverless.UnitTests.OrdersProcessor.csproj
  • SW.Serverless.UnitTests.OrdersSource/Program.cs
  • SW.Serverless.UnitTests.OrdersSource/SW.Serverless.UnitTests.OrdersSource.csproj
  • SW.Serverless.UnitTests/DescribeTests.cs
  • SW.Serverless.UnitTests/GrpcClassicTests.cs
  • SW.Serverless.UnitTests/NodeAdapterTests.cs
  • SW.Serverless.UnitTests/NodeAdapters/classic.js
  • SW.Serverless.UnitTests/NodeAdapters/orders_processor.js
  • SW.Serverless.UnitTests/NodeAdapters/orders_processor.ts
  • SW.Serverless.UnitTests/NodeAdapters/orders_source.js
  • SW.Serverless.UnitTests/NodeAdapters/resident.js
  • SW.Serverless.UnitTests/PythonAdapterTests.cs
  • SW.Serverless.UnitTests/PythonAdapters/classic.py
  • SW.Serverless.UnitTests/PythonAdapters/orders_processor.py
  • SW.Serverless.UnitTests/PythonAdapters/orders_source.py
  • SW.Serverless.UnitTests/PythonAdapters/resident.py
  • SW.Serverless.UnitTests/RegistrationTests.cs
  • SW.Serverless.UnitTests/ResourceLimitTests.cs
  • SW.Serverless.sln
  • SW.Serverless/Extensions/IServiceCollectionExtensions.cs
  • SW.Serverless/Resident/AdapterHostService.cs
  • SW.Serverless/Resident/AdapterMetrics.cs
  • SW.Serverless/Resident/AdapterPool.cs
  • SW.Serverless/Resident/AdapterProcessLauncher.cs
  • SW.Serverless/Resident/AdapterSpec.cs
  • SW.Serverless/Resident/IAdapterEventSink.cs
  • SW.Serverless/Resident/IAdapterStateStore.cs
  • SW.Serverless/Resident/IResidentAdapterHost.cs
  • SW.Serverless/Resident/IResidentAdapterLocator.cs
  • SW.Serverless/Resident/InstanceHealth.cs
  • SW.Serverless/Resident/ResidentAdapterHost.cs
  • SW.Serverless/Resident/ResidentAdapterInstance.cs
  • SW.Serverless/Resident/ResidentOptions.cs
  • SW.Serverless/SW.Serverless.csproj
  • SW.Serverless/Services/ServerlessService.cs
  • docs/README.md
  • docs/cli.md
  • docs/compatibility.md
  • docs/concepts.md
  • docs/contracts.md
  • docs/extending.md
  • docs/hosting.md
  • docs/manifest.md
  • docs/packaging-and-storage.md
  • docs/protocol.md
  • docs/resident-adapters-design.md
  • docs/writing-adapters.md
  • scripts/install-cli.sh
  • sdk/node/README.md
  • sdk/node/package.json
  • sdk/node/src/index.d.ts
  • sdk/node/src/index.js
  • sdk/node/src/wire.js
  • sdk/node/test/sdk.test.js
  • sdk/python/.gitignore
  • sdk/python/README.md
  • sdk/python/pyproject.toml
  • sdk/python/src/sw_serverless/__init__.py
  • sdk/python/src/sw_serverless/_adapter.py
  • sdk/python/src/sw_serverless/_hpack.py
  • sdk/python/src/sw_serverless/_http2.py
  • sdk/python/src/sw_serverless/_huffman.py
  • sdk/python/src/sw_serverless/_runner.py
  • sdk/python/src/sw_serverless/_types.py
  • sdk/python/src/sw_serverless/_wire.py
  • sdk/python/tests/test_adapter.py
  • sdk/python/tests/test_wire.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@samerzughul
samerzughul merged commit 5c480de into main Oct 10, 2026
10 checks passed
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