Skip to content

feat(e2e): standin Suite 5+6 — Rust provider-stack alongside Deno#123

Merged
AquiGorka merged 2 commits into
mainfrom
feat/standin-e2e
Jun 18, 2026
Merged

feat(e2e): standin Suite 5+6 — Rust provider-stack alongside Deno#123
AquiGorka merged 2 commits into
mainfrom
feat/standin-e2e

Conversation

@AquiGorka

Copy link
Copy Markdown
Contributor

Summary

Adds end-to-end coverage for the Rust provider-stack standin as a first-class service in local-dev. The standin runs on the same infra cycle as the Deno provider-platform — separate port, separate DB, separate OTEL service name — so a single ./up.sh brings both up and a single ./testnet/run-local.sh all exercises both end to end.

What changed

Infra — the standin becomes a first-class service

  • lib/master-seed.ts: new ROLES.STANDIN_PP role. Deterministic per master seed; distinct from ROLES.PP so the standin's chain identity doesn't collide with the Deno PP.
  • setup-keys.sh: emits STANDIN_PP_PK / STANDIN_PP_SK to .local-dev-keys.
  • infra-up.sh: new section 5b spawns the Rust standin alongside the Deno provider — $BASE_DIR/provider-stack/target/release/provider-stack, port 3011, OTEL_SERVICE_NAME=provider-platform-standin, dedicated provider_stack_db auto-created on the existing postgres. Best-effort: skipped with a warning if the binary or keys aren't there yet.
  • infra-up.sh: pinned stellar container start local to --image-tag-override v639-b1103.1-latest — the rolling :testing tag has been rejecting all WASM uploads with HostError(Context, InternalError) since 2026-06-15. PR fix(ci): pin stellar/quickstart to v639-b1103.1-latest (node regression) #120 pinned the docker-compose paths; this pins the CLI path used by up.sh.
  • down.sh: also stops .standin.pid so a re-up doesn't leak the previous standin onto port 3011.

Test — new Suites 5 + 6

  • lifecycle/standin-verify.ts (new): mirror of testnet-verify.ts pointed at :3011 with PP derived from ROLES.STANDIN_PP. Single-PP: no /dashboard/pp/register step (the standin's PP is env-pinned at boot). The rest of the flow (deploy → council → join → approve → on-chain add_provider → watcher promote ACTIVE → deposit/send/withdraw) is byte-identical.
  • lifecycle/standin-verify-otel-local.ts (new): wraps the OTEL verifier with providerServiceOverride: "provider-platform-standin" so it queries the standin's traces specifically.
  • lib/verify-otel-local.ts: new optional providerServiceOverride option. Used only by the standin wrapper; Deno path unchanged.
  • lib/client/{config,bundle,register-entity}.ts: optional urlShape: "multi-pp" | "single-pp" (default multi-pp). When single-pp, bundle URLs become /api/v1/provider/entity/bundles and the entity-register endpoint becomes /api/v1/provider/entities — matching the standin's single-PP route shape. Defaulting to multi-pp keeps every existing Deno call site behaviour-identical.
  • testnet/events-capture/{harness,subscribe}.ts: per-script config (ppRole, perSuiteSecret, urlShape) lets the standin script use ROLES.STANDIN_PP, skip the per-suite KDF (the standin's PP is fixed at boot, not per-suite-derived), and use the single-PP WS URL + /dashboard/pp (singular) sanity check.
  • testnet/run-local.sh: new Suite 5 (lifecycle → standin via events-capture) + Suite 6 (OTEL verify standin), standin alias, extends all to run all six.

Validation

./testnet/run-local.sh standin15 consecutive runs, every assertion green:

metric result
Suite 5 lifecycle PASS every run
per-PP WS events 12/12 every run
network WS events 5/5 every run
Suite 6 OTEL spans 23 passed, 0 failed every run

Same env-pinned PP (GBKV…CV7FR) on every run, no flakes.

Test plan

  • ./down.sh && ./up.sh && ./setup-c.sh
  • ./testnet/run-local.sh standin — Suite 5+6 alone, both green
  • ./testnet/run-local.sh all — Deno (1-4) + standin (5-6) all six green
  • Re-run standin several times against the same stack — verify stable

Adds end-to-end coverage for the Rust provider-stack standin
(https://github.com/Moonlight-Protocol/provider-stack) as a first-class
service in local-dev. The standin runs ON THE SAME stack as the Deno
provider-platform, on a separate port, with distinct keys, distinct DB,
and distinct OTEL service name — so both can be exercised in the same
infra cycle.

What landed
-----------

Infra (the standin becomes a first-class service):
  - lib/master-seed.ts: new ROLES.STANDIN_PP role (deterministic per
    master seed). Distinct from ROLES.PP so the standin's chain identity
    doesn't collide with the Deno PP.
  - setup-keys.sh: emits STANDIN_PP_PK / STANDIN_PP_SK to
    `.local-dev-keys` for downstream consumers.
  - infra-up.sh: new section 5b spawns the Rust standin alongside the
    Deno provider (`$BASE_DIR/provider-stack/target/release/provider-stack`,
    port 3011, OTEL_SERVICE_NAME=provider-platform-standin, dedicated DB
    `provider_stack_db` auto-created on the existing postgres). Best-effort:
    skipped with a warning if the binary or keys aren't there yet.
  - infra-up.sh: pinned `stellar container start local` to
    `--image-tag-override v639-b1103.1-latest` (the working tag from
    PR #120 — the rolling `:testing` tag has been rejecting WASM uploads
    with HostError(Context, InternalError) since 2026-06-15). #120 pinned
    the docker-compose paths; this pins the CLI path used by up.sh.
  - down.sh: also stops `.standin.pid` so a re-up doesn't leak the
    previous standin process onto port 3011.

Test (the new Suites 5 + 6):
  - lifecycle/standin-verify.ts (new): mirror of testnet-verify.ts pointed
    at :3011 with PP derived from ROLES.STANDIN_PP. Single-PP: no
    /dashboard/pp/register step (the standin's PP is env-pinned at boot).
    The rest of the flow (deploy → council → join → approve → on-chain
    add_provider → watcher promote ACTIVE → deposit/send/withdraw) is
    byte-identical to testnet-verify.ts.
  - lifecycle/standin-verify-otel-local.ts (new): wraps the OTEL verifier
    with `providerServiceOverride: "provider-platform-standin"` so it
    queries the standin's traces specifically (without disturbing the
    existing Deno-side verify).
  - lib/verify-otel-local.ts: new optional `providerServiceOverride`
    option. Threaded only by the standin verify wrapper; unused on the
    Deno path.
  - lib/client/config.ts + bundle.ts + register-entity.ts: optional
    `urlShape: "multi-pp" | "single-pp"` (default multi-pp). When
    single-pp, bundle URLs become `/api/v1/provider/entity/bundles` and
    the entity-register endpoint becomes `/api/v1/provider/entities` —
    matching the standin's single-PP route shape. Defaulting to multi-pp
    keeps every existing Deno-targeted call site unchanged.
  - testnet/events-capture/harness.ts + subscribe.ts: per-script config
    (ppRole, perSuiteSecret, urlShape) lets the standin script use
    ROLES.STANDIN_PP, skip the per-suite KDF (the standin's PP is fixed
    at boot, not per-suite-derived), and use the single-PP WS URL +
    /dashboard/pp (singular) sanity check.
  - testnet/run-local.sh: new Suite 5 (lifecycle → standin via
    events-capture) + Suite 6 (OTEL verify standin), `standin` alias,
    extends `all` to run all six.

Validation
----------

`./testnet/run-local.sh standin` run 15 times from a stable infra. Every
run green:

  perPp:GBKVLUPENRSLQCHPCBJM4HGPIJP43LWIURGWQNBJAQ5JXIVKVHKCV7FR: 12/12
  network: 5/5
  OTEL: 23 passed, 0 failed

Same env-pinned PP across every run, no flakes.
@AquiGorka AquiGorka merged commit a4aecad into main Jun 18, 2026
10 checks passed
@AquiGorka AquiGorka deleted the feat/standin-e2e branch June 18, 2026 20:53
pselle added a commit that referenced this pull request Jul 7, 2026
## Summary
- The `.local-dev-keys` snapshot committed on `main` predates #123 (Rust
provider-stack standin), which added a `STANDIN_PP` role to
`setup-keys.sh`'s `ROLES` map
- All keys derive deterministically from the shared local-dev master
seed (`lib/master-seed.ts`), and `up.sh` regenerates this file on every
run — this PR just brings the checked-in copy back in sync with what
`setup-keys.sh` actually outputs today
- No values changed for any pre-existing role (`ADMIN`, `PP`, `OPEX`,
`PAY_ADMIN`, `PAY_SERVICE`, `ALICE`, `BOB`); only the new
`STANDIN_PP_PK`/`STANDIN_PP_SK` pair and the regeneration timestamp are
added

## Test plan
- [x] Diffed against a fresh `./setup-keys.sh` run — output matches this
file exactly (modulo timestamp)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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