Status: implemented
The example suite uses the existing production P0 service for trusted CI runs.
GitHub Actions supplies RATELIMITLY_AUTH_KEY from a CI-only repository secret.
The client decodes the key ID, builds the key-derived tenant name, performs SRV
discovery under P0, and resolves the selected server. The workflow does not
store a concrete tenant, host, port, or server identity.
The public repository never checks out, downloads, builds, or publishes the private server binary or source. CI interacts only with the public DNS and UDP data plane exposed to normal clients.
Live traffic is restricted to trusted main pushes and manual runs of main by
edescourtis. Pull requests, forks, and feature-branch dispatches are
synthetic-only. This prevents code that has not reached the trusted branch from
receiving the production credential.
flowchart TD
Change["Pull request, fork, or feature branch"] --> Synthetic["Authenticated synthetic responder tests"]
Main["Trusted main push or owner dispatch"] --> Synthetic
Main --> Examples["22 production P0 example integrations"]
Main --> Probe["Dedicated production protocol probe"]
Examples --> LocalProof["Real discovery, admission, work, and local report-send success"]
Probe --> ServerProof["Server-observed 37 ms latency and rate-limited outcome"]
Mac["Developer Mac"] --> MacOnly["Local kqueue and libdispatch scenarios"]
No single check proves every useful property safely and deterministically. The suite combines three layers:
This distinction matters because r_client_report_latency() is
fire-and-forget. A successful return proves that the client encoded and sent the
datagram; it is not a server acknowledgement. Therefore, an individual
production example run does not prove that production accepted its report. The
dedicated probe closes that protocol-level gap by reading the reported value
back through a later admission request.
| Trigger | Revision trusted? | Synthetic tests | Production P0 | Secret exposed to a test step? |
|---|---|---|---|---|
| Pull request, including a fork | No | Yes | No | No |
| Feature-branch push | No | Workflow is not triggered | No | No |
| Feature-branch dispatch | No | Yes | No | No |
Push to main |
Yes | Yes | Yes | Only the bounded live steps |
Manual dispatch of main by edescourtis |
Yes | Yes | Yes | Only the bounded live steps |
Manual dispatch of main by another actor |
Revision is trusted, actor is not authorized | Yes | No | No |
The workflow uses read-only repository contents permission. Production step
conditions are evaluated before the repository secret is attached to the step.
There is no pull_request_target or privileged follow-up workflow that executes
pull-request code with the key.
The 11 one-shot entries run on Ubuntu:
The executable source of truth is
tests/linux-one-shot-examples.txt.
The 10 HTTP integrations run in three Ubuntu shards:
The executable source of truth is
tests/linux-http-examples.txt. Each row
records its shard, executable, local HTTP port, metrics label, expected
resource-denial status, and launch model.
The Win32 example has two independent production lanes:
windows-latest.The Wine build uses a Windows-targeted static OpenSSL archive, checks the PE architecture, and rejects dynamic OpenSSL imports. The native lane verifies that CMake selected the Microsoft C compiler and also builds a portable Mongoose example with MSVC.
The core library still builds and runs its unit tests on macos-latest.
Platform-specific kqueue and libdispatch remain local-only because that was the
chosen CI boundary. On a developer Mac, run:
bash tests/test_macos_examples.sh
That local matrix executes the same deterministic admitted, resource-denied, and latency-denied behaviors. It does not use the production secret.
Every Linux matrix entry and the Win32 integration runs against the repository’s authenticated synthetic UDP responder. Each example must demonstrate:
The HTTP harness also verifies the framework’s documented status mapping and that an unprotected readiness route emits no Ratelimitly traffic. This is the per-example proof that both the rate limiter and latency tracker are wired correctly.
Each of the 22 CI-eligible examples then starts with only the authentication key and no tenant or fixed-endpoint override. The live runner requires:
This layer deliberately does not force every shared production bucket into a denial state. Deterministic tests cover that branch per example without making cloud tests race or leave disruptive counters behind.
Every trusted-main production call uses the same conservative request profile:
a 25 ms scheduling unit, three internal request replays, and one final receive
unit. The maximum admission wait is therefore
(3 + 2) * 25 ms = 125 ms. Each runner executes its process once; replay is
performed inside the client with the original deduplication identity. Release
artifacts and non-production calls retain the normal default of a 20 ms unit,
one replay, and a 60 ms maximum wait.
Production runners also enable the credential-free request profile log. Every completed admission reports the client-side wait, configured unit and replay count, completion round, round/final phase, status, and whether a response was selected. The wait starts with the initial UDP send attempt and ends at client completion; it excludes DNS discovery, protected work, latency reporting, and process cleanup. The single-request example runners validate these lines before publishing them to the CI log. The multi-request semantic probe publishes one line for each admission. A green production run therefore records both the intended 25 ms / three-replay policy and each observed scheduler path.
tests/production_p0_probe.c uses names scoped
to the GitHub run and attempt. It performs two independent proofs:
rate_limited, carry a
positive token deficit, and leave latency_limited clear.This probe is the server-observed semantic check. Its unique names avoid stale state without requiring administrative APIs or access to private server logs.
The repository credential identifies shared production state, so repeated runs of the same fixed example identities must not overlap. CI uses non-cancelling concurrency groups:
These groups are intentionally not one global lock. The HTTP shards use distinct framework bucket and service names and can run concurrently. A feature-branch dispatch uses a revision-specific non-production group, so it cannot delay a trusted production run.
Example latency trackers retain samples for ten seconds. Matrix runners wait 11 seconds before their first live request, which lets state from a cancelled or failed predecessor expire. They wait once per matrix rather than once per example because each example owns distinct bucket and service identities.
The key is never placed in a command argument, committed file, artifact, or
fixed endpoint. The runners reject and unset RATELIMITLY_TENANT,
RATELIMITLY_EXAMPLE_SERVER_HOST, and
RATELIMITLY_EXAMPLE_SERVER_PORT so live tests cannot silently bypass
key-derived discovery.
Handling differs by platform because process APIs differ:
ProcessStartInfo environment for the
MSVC child, removes discovery overrides, and clears the key from that object
immediately after CreateProcess copies it.HTTP and Wine runners fail closed if core dumps cannot be disabled. All live runners enforce process deadlines and avoid printing the environment wholesale. Any runner that replays child or dependency output sanitizes it first.
| Failure | Likely layer | First evidence to inspect |
|---|---|---|
| Synthetic allow/deny assertion | Example integration | Scenario name and sanitized responder records |
| DNS or admission timeout across many examples | Production fixture or network | First failing matrix and runtime status |
| One framework times out while peers pass | Framework lifecycle or sandbox | Framework log and forced-shutdown result |
| Local latency-report error | Example/runtime send path | Sanitized framework stderr |
| Exact 37 ms read-back fails | Server latency semantics | Dedicated probe’s last observed value |
| Second one-token request is not rate-limited | Server rate semantics or stale identity | Dedicated probe’s rate/deficit fields |
A broad production outage can make trusted-main CI red even when deterministic tests pass. That is expected: the production layer is a compatibility smoke test, not a hermetic unit test. The deterministic layer remains the primary diagnostic for example regressions.
| Purpose | File |
|---|---|
| Workflow and trust conditions | .github/workflows/ci.yml |
| One-shot deterministic matrix | tests/test_linux_one_shot_examples.sh |
| HTTP deterministic matrix | tests/test_linux_http_examples.sh |
| One-shot production runner | tests/test_production_p0_one_shot_examples.sh |
| HTTP production matrix | tests/test_production_p0_http_examples.sh |
| Per-framework production runner | tests/run_production_p0_http_example.sh |
| Native Windows production runner | tests/test_production_p0_win32_example.ps1 |
| Wine production runner | tests/test_production_p0_win32_wine.sh |
| Dedicated semantic probe | tests/test_production_p0.sh |
| Shared production request profile | tests/production_p0_profile.sh |
| CI and documentation contract | tests/test_examples.sh |
When adding or changing an example:
When rotating the CI key, update only the RATELIMITLY_AUTH_KEY repository
secret. Do not add the derived tenant or resolved server endpoints to the
workflow. A key change naturally selects new key-derived state, so the next
trusted run should be treated as a fresh compatibility check.