Skip to content

Rust #325: import embedded v2 workflow histories like Server 2.11.1 - #764

Merged
rmcdaniel merged 15 commits into
mainfrom
rust-325-workflow-import
Oct 25, 2026
Merged

rmcdaniel merged 15 commits into
mainfrom
rust-325-workflow-import

Conversation

@rmcdaniel

Copy link
Copy Markdown
Member

Native serves POST /api/workflows/import/embedded-v2 as published Server 2.11.1 does (Workflow 2.10.2's EmbeddedV2ImportController and EmbeddedV2HistoryImport), bringing native to 139 of the 175 published route methods.

Fixture (d31d1b460), recorded from published 2.11.1

Bundles are built from real published exports: a completed run with an activity, timer, signal, memo and search attributes; a terminated run; and a running run. The fixture covers:

  • the request gates and body shapes;
  • a dry run, an import, and idempotent and conflicting repeats;
  • integrity and signature refusals, and each eligibility rule;
  • request normalization before the checksum, bare bundles, and a failed write;
  • non-terminal imports, and the imported run read back through describe, runs, history and list.

It was recorded three times with identical results. It also bounds two published defects: the importer finds runs and instances in every namespace, so a bundle imported in another namespace answers already_imported, and an import takes over another namespace's instance. Native refuses both: a run id held in another namespace is a run_id_conflict, and another namespace's instance is refused rather than taken over.

Native (2c9905189, 864cadd28)

  • Request reading: the request is read as PHP reads it. That means json_decode with PHP's key types, ordering and int/float rules, Laravel's TrimStrings and ConvertEmptyStringsToNull, and options from the body, then the query.
  • Integrity report: BundleIntegrityVerifier's report keeps PHP's check order, rules, messages, paths and contexts. The checksum and HMAC-SHA256 signature are computed over PHP's canonical JSON and compared in constant time.
  • Eligibility and writes: the eligibility rules, the dry run, idempotent and conflicting repeats, and the write of every bundle section run in one transaction. The run summary is projected from the imported rows, with the embedded import's engine source.
  • Access: admin-only, writing into the requested namespace.
  • Parsing cost: JSON objects and Avro maps are parsed in linear time. A repeated key keeps its first position with the last value, as in PHP.
  • Shared reads now matching 2.11.1 for every run: describe shows each command's recorded reason when the command was not rejected (inline payloads up to 8 KiB; every writer caps the reason at 1000 characters). History reports the run's compatibility, compatibility_status, compatibility_supported_in_fleet and compatibility_fleet_reason, as HistoryController::show does.
  • rust/tests/fixtures/unserved-php-routes.v2.11.1.txt drops the route. The doc's missing-route list now names only Waterline v1 import, and no longer lists worker sessions or activity cancellation acknowledgement, both served on main.

Qualification

  • This head, merged with main through CI: run the six deadline-health cells in turn on one runner #748: the SQLite library suite passes (284; 36 database qualifications ignored), as does the execution suite (492). The PostgreSQL qualification tests pass 12/12 and the MySQL ones 18/18, against disposable pinned databases.
  • Earlier on the branch: the workflow-import fixture recorded from published 2.11.1 passed against native on SQLite, PostgreSQL 17, MySQL 8.0 and MariaDB 10.11, and every shared fixture passed against native on SQLite.
  • Comparator node tests pass 2268/2268, and the Docker isolation policy passes.
  • CI runs the fixture and every part on all databases.

No PHP application or fixture-expectation changes beyond the new fixture.

🤖 Generated with Claude Code

rmcdaniel and others added 10 commits October 24, 2026 15:01
…ished 2.11.1

POST /api/workflows/import/embedded-v2 from bundles built out of real
published exports (a completed run with an activity, timer, signal, memo and
search attributes; a terminated run; a running run): the request gates, body
shapes, a dry run, an import, idempotent and conflicting repeats, integrity
and signature refusals, each eligibility rule, request normalization before
the checksum, bare bundles, a failed write, non-terminal imports, and the
imported run through describe, runs, history and list. Recorded three times,
identical. Two published defects are bounded: the importer finds runs and
instances in every namespace, so a bundle imported elsewhere answers
already_imported and an import takes over an instance of another namespace.
Native now serves POST /api/workflows/import/embedded-v2 as published
Server 2.11.1 does with Workflow 2.10.2 (EmbeddedV2ImportController and
EmbeddedV2HistoryImport):

- The request is read as PHP reads it: json_decode with PHP's key types,
  order and int/float rules, Laravel's TrimStrings and
  ConvertEmptyStringsToNull, and options from the body, then the query.
- BundleIntegrityVerifier's report keeps PHP's check order, rules,
  messages, paths and contexts. The checksum and HMAC-SHA256 signature are
  computed over PHP's canonical JSON and compared in constant time.
- The eligibility rules, the dry run, idempotent and conflicting repeats,
  and the write of every bundle section run in one transaction. The run's
  summary is projected from the imported rows, with the embedded import's
  engine source.
- The route is admin-only and writes into the requested namespace. A
  bundle counts as already imported only in that namespace; a run id held
  in another namespace is a run_id_conflict, and an instance of another
  namespace is refused rather than taken over. The fixture bounds the
  published cross-namespace answers as defects.
- JSON objects and Avro maps are parsed in linear time; a repeated key
  keeps its first position with the last value, as in PHP.

Two shared reads now match published 2.11.1 for every run, which the
import fixture exposed:

- Describe shows the reason each command's payload records
  (commandReason) when the command was not rejected. Only inline payloads
  up to 8 KiB are read; every writer caps the reason at 1000 characters.
- History reports the run's compatibility, compatibility_status,
  compatibility_supported_in_fleet and compatibility_fleet_reason, as
  HistoryController::show does, and the control plane carries
  compatibility.

Three stale unit expectations are corrected: published PHP's canonical
JSON (JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION) and
json_encode both escape non-ASCII characters and line separators.

Qualified locally: the workflow-import fixture recorded from published
2.11.1 passes against native on SQLite, PostgreSQL 17, MySQL 8.0 and
MariaDB 10.11; every shared fixture passes against native on SQLite; and
the SQLite all-targets suite passes (265 unit, 454 execution).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	.github/workflows/server-parity.yml
…workflow-import

Both sides described omitted command previews. Main reads native stored
references (a start's payload and a signal's arguments) through
per-backend exact-prefix comparisons. This branch also recognised PHP's
own external references, which an imported history keeps. The merged
query keeps main's comparisons and adds two columns in the same style:
php_payload_reference (exact 23-byte PHP prefix) and reason_payload for
commandReason(), which never reads either kind of reference. A preview
is omitted when either reference is oversized. The query test now pins
both new comparisons and still refuses LIKE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The unserved-route list arrived with #745 and still named it, so
route_coverage failed after the merge. Native serves 131 of the 175
published route methods on this branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto rust-325-workflow-import

Native now serves 139 route methods: main's 138 plus embedded v2 import.
The runtime keeps both new modules, and the comparator node test list
keeps both sides' tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ment served

Both are served on main (worker sessions since #740), but the missing
route list still named them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ust-325-workflow-import

The comparator node test list keeps both sides' tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

The two published PHP defects this fixture bounds (cross_namespace_duplicate, cross_namespace_instance_attach) are now tracked as #765, the PHP-side fix. Native already refuses both. The fixture's published_defects entries will gain the issue link in the next fixture-touching change, so this head's CI doesn't restart for metadata.

SonarCloud rust:S3776 on #764: check_payload_manifest (31) and
Parser::value (33) exceeded the cognitive complexity limit of 30.

check_manifest_entry now holds one payload manifest entry's checks, in
the same order. Parser::json_list and Parser::json_object hold the JSON
array and object parsing that value() delegated to nested() as closures.
Behavior is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

New exact head 8efdfe04dc4528211cb42a1e1ace1233d31d4e78, one commit on d5a8380e3 (which was fully green). SonarCloud reported two rust:S3776 cognitive-complexity findings: bundle_verifier.rs check_payload_manifest at 31 and php_value.rs Parser::value at 33, against a limit of 30. One payload manifest entry's checks move unchanged into check_manifest_entry, in the same order, and the JSON array and object parsing moves into Parser::json_list and Parser::json_object, which value() passes to nested(). Behavior is unchanged. The full SQLite suite passes on this head (library 284, execution 492). CI is running.

@rmcdaniel

Copy link
Copy Markdown
Member Author

PHPUnit Feature on 8efdfe04d (run 40221723442) had one error: WorkflowTaskRepairRaceTest::test_repair_can_lock_tasks_while_a_worker_mutation_waits_for_the_run (mysql, waiting_history) got SQLSTATE[HY000] [2002] Connection refused from the job's own MySQL container (dw-server-backup-mysql-…) during a migration. That's transient infrastructure. The commit since the green d5a8380e3 touches only Rust (bundle_verifier.rs, php_value.rs), and the PHP suite passed on that earlier head. I've rerun only the failed PHPUnit jobs.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security review blocker at exact head 8efdfe04dc4528211cb42a1e1ace1233d31d4e78:

Cross-namespace lineage rows remain writable through import. The new run/instance guards correctly refuse the two published defects already recorded in #765, but the link writer still accepts each bundle-supplied opposite endpoint without checking its namespace. In workflow_import.rs, a parent entry forces only the imported run's child endpoint and trusts the supplied parent IDs; a child entry does the inverse, then inserts the global workflow_links row. There is no namespace predicate or related-run/instance ownership check.

That row is observable from the other namespace: history_export.rs selects links by the other run ID and joins workflow_runs without a namespace predicate. An import into A can therefore attach A to an existing run in B, change B's exported lineage, and expose B's related-run metadata in A's export. Other runtime paths also traverse workflow_links (continuation/cancellation/child logic), so this is not merely a report-count discrepancy.

The route being global-admin-only limits who can trigger it today, but #765 explicitly establishes namespace isolation as an invariant and this still lets one requested namespace mutate another namespace's durable view. Current fixture bundles have empty parent/child link lists, so the two cross-namespace controls do not cover this path.

Please hold merge and add atomic negative controls for both parent and child directions. The implementation needs to prevent existing foreign endpoints and also define a safe rule for dangling related IDs (otherwise a link admitted before the related run exists can become cross-namespace later). Preserve both namespaces on refusal. I recommend extending #765 with this third published/native path and covering the relevant database families. No live environment was touched.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Follow-up: the blocker is broader than workflow_links and includes a direct post-import cross-namespace mutation path.

The importer copies bundle-supplied signals[*].command_id and updates[*].command_id without requiring that command to belong to the imported run (signal write, update write). A crafted bundle imported into namespace A can therefore point one of these records at an existing command in namespace B.

Later, ordinary A-namespace execution follows that reference and updates the command by ID alone:

  • signal application joins the referenced command and then runs UPDATE workflow_commands SET applied_at=... WHERE id=... (store.rs);
  • update application joins the referenced command and then writes its outcome/applied time by ID alone (updates.rs, updates.rs).

So an A worker can complete imported A work and mutate B's durable command row. The unscoped command/signal/update join in history export also lets the A row alter B's exported command projection. Integrity/checksum verification does not validate this relational ownership.

Please treat this as the same merge blocker but fix/test the whole imported reference graph, not only lineage. At minimum, signal/update command references must resolve to a command imported for this exact run/instance (or the import must refuse atomically). Add negative controls for foreign signal and update command IDs that exercise the later application path and prove the foreign command and both namespaces remain byte-for-byte unchanged. Other copied reference fields should be audited for the same ownership property before acceptance.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Additional acceptance gap at exact head 8efdfe0: the Rust role-token test and admission-role-tokens fixture do not mention POST /api/workflows/import/embedded-v2, while the new import probe only uses the legacy/admin token. The guard source classifies the route as admin-only correctly, but this bulk durable-state write needs an executable role boundary: worker and operator must receive 403 before controller execution, while admin reaches the controller. Please add those negative/positive controls with unchanged state.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security hardening required before acceptance: request() currently accepts signing_key from the URI query just like non-secret options, and the handler parses the full URI. An HMAC key in a URL can be retained by reverse-proxy access logs, tracing, browser/client history, and telemetry even though native does not echo the value. Please restrict signing_key to a protected JSON body field or the configured runtime secret, keep non-secret options in the query if parity requires them, and add a sentinel test proving the value is absent from responses/diagnostics. If this intentionally diverges from published PHP, record the PHP-side defect separately. I am not claiming the current native logger emitted a key; this is an ingress design exposure.

Security review of #764 (Server #765): published PHP copies every reference
an import bundle carries, and native copied them too. A bundle imported into
one namespace could link its run to another namespace's run, point its
signals and updates at another workflow's commands (which later application
updates by id), and point its tasks at another run's activities (which a lost
lease settles by id). The signing key was also read from the URL.

Native now refuses such a bundle before writing anything:

- Every copied reference must name a row this import writes, of the expected
  kind: signal and update commands, update failures, event tasks and
  commands, activity attempts and their tasks, task payload references, the
  archive command and activity failure sources (`references.unresolved`).
  Resolved runs must be the imported run (`references.foreign_run`), and a
  link may not name the imported run itself (`references.self_link`).
- In the write transaction, a requested run must be another run of the same
  workflow in this namespace, and a failed update's failure outside the
  bundle must belong to no run.
- A lineage link is written only when its related run exists in this
  namespace and its instance. A related run or instance of another namespace
  fails the import. A related run that exists nowhere yet is not written;
  its own import writes the link once both runs exist, so no stored link can
  later capture a run created elsewhere.
- signing_key is read only from the body or the configured secret; in the
  query string, in any spelling, it is refused with 422 signing_key_in_query
  and never repeated.

Defense in depth for rows no import can now write: signal and update
application join and update their command only within their own instance
(typed 409 signal_command_unavailable / update_command_unavailable instead of
a foreign mutation), the described-command and export joins require the same
instance, history export omits related runs of another namespace, and
lost-lease settlement reads only the task's own run's activity.

tests/execution/workflow_import_fences.rs covers both lineage directions, a
foreign instance, a deferred link a later foreign run never captures, each
foreign row reference, forged signal and update rows at application, worker
and operator 403s against the admin positive control, and the URL signing
key, each against a byte-for-byte export snapshot of the other namespace.
Without the fences and predicates five of the seven fail. Full execution
suites pass on SQLite, PostgreSQL and MySQL (499 each).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

New exact head 6f109c2c118bf3c3c309eb606631357d5a29e6a4 for re-review. It addresses all four Security findings: 6401697580, 6401743617, 6401767344 and 6401790718.

What changed (the commit message has the detail; the field-by-field audit is on #765):

  • Bundle references. Every copied reference must name a row of this bundle, refused as references.unresolved, references.foreign_run or references.self_link.
  • Store references. Requested runs and dangling update failures are checked against the store in the write transaction.
  • Lineage. A link is written only between existing runs of one namespace. A related run or instance in another namespace fails the import, and a related run that exists nowhere yet isn't written.
  • Defense in depth. Signal and update application, the described-command and export joins, history export lineage, and lost-lease settlement are now scoped to their own instance or run.
  • Signing key. It's read only from the body. In the URL, in any spelling, it's refused with 422 signing_key_in_query.

Evidence.

  • rust/tests/execution/workflow_import_fences.rs has seven tests and runs on each backend. Every refusal is checked against a byte-for-byte export snapshot of the other namespace:
    • lineage refused in both directions, for a foreign instance, and for a self-link;
    • a deferred link that a run later imported into another namespace never captures, plus a same-namespace positive control;
    • eight foreign row references (signal command, update command, activity task, current attempt, event command, resolved run, requested run, update failure), each refused, with the untouched bundle importing as the control;
    • a forged signal record naming another namespace's same-sequence update command, and a forged update naming another namespace's signal command. Each is refused at worker application with a typed 409, and the foreign command is unchanged;
    • worker and operator get 403 with no write, and admin imports;
    • a URL signing key in both spellings is refused and never repeated, while one in the body is read and never echoed.
  • Mutation check. With the fence, the store checks and the new predicates removed, five of the seven fail. The import refusals got 201, the deferred link was written, and the forged update completed with 200.
  • Local suites. SQLite library 284 and execution 499; PostgreSQL 17 execution 499; MySQL 8.0 execution 499.

🤖 Generated with Claude Code

General showed on PostgreSQL that published PHP's import, with deferred
links, loses a reciprocal link when parent and child import concurrently:
each sees the other uncommitted and skips it. Native serializes durable
transactions (PostgreSQL's transaction advisory lock, MySQL's ownership row
FOR UPDATE, SQLite's single writer), so the second import sees the first
run committed and writes the link. The new test dispatches both imports
from two runtimes at once and requires both imported with exactly one link.
It passes on SQLite, PostgreSQL and MySQL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

New exact head: 9ae2934a9580b3b7cb828814503fddbe702aedea. The only change from 6f109c2c1 is one new test, reciprocal_imports_at_the_same_moment_write_their_link_once.

General showed on PostgreSQL that a deferred link can be lost when parent and child import concurrently: each sees the other uncommitted. Native doesn't hit this, because every durable transaction is serialized: PostgreSQL's pg_advisory_xact_lock in begin(), MySQL's ownership row FOR UPDATE, and SQLite's single writer. The test imports both bundles from two runtimes at once and requires both imported with exactly one link. It passes on SQLite, PostgreSQL 17 and MySQL 8.0, and the other seven fence tests pass on each as well. I haven't shown it failing with that lock removed, because the same lock guards every transaction.

🤖 Generated with Claude Code

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security source re-review is complete at exact head 9ae2934a9580b3b7cb828814503fddbe702aedea (merge base 4e7955473e56007b1640fbb56a58d630db1d3eb4). I find no remaining source blocker in the four boundaries previously raised.

  • Imported lineage is checked inside the serialized write transaction against the related run's namespace and named instance. A missing related run produces no stored edge, and the reciprocal-import regression at this head proves the second serialized transaction writes the one edge.
  • Writer-selected bundle IDs fence command, task, activity/attempt, timer, signal/update, failure-source and historical row references. Requested runs must be runs of the same workflow in the same namespace. Defense-in-depth runtime joins/updates now carry the owning instance or run predicate, so a forged legacy row cannot mutate another workflow.
  • The HTTP guard makes every workflow-import route admin-only under configured authentication. Worker and operator tokens are negative controls.
  • The decoded query is rejected if it contains any signing_key... key; the signing key is accepted only from the body/configured secret and is not copied into the response.

I separately traced workflow_updates.failure_id. Outside import it is validated as a non-empty failure receipt identifier and returned/exported as recorded; it is not used to join, mutate, retain or authorize a workflow_failures row. The import transaction rejects an identifier already owned by any failure, while an as-yet-unowned identifier is inert. A later same-string failure therefore does not create a cross-run execution path.

The concurrency claim is supported in source on all three backends: SQLite uses BEGIN IMMEDIATE, PostgreSQL takes the process-independent transaction advisory lock, and MySQL locks the single schema ownership row for the transaction.

This is Security acceptance of the exact source head only. I did not run Rust builds on the lab host. The current hosted matrix is still pending and must pass; merge/release/installed-image qualification and the published PHP-side correction remain separate gates.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security source re-ack for exact head 5eea6e2.\n\nGit-object verification:\n- parents are exactly the previously accepted 9ae2934 and merged CI commit f63f6c4;\n- 9ae2934..5eea6e2 changes only .github/workflows/phpunit-feature.yml;\n- every path outside that workflow is byte-identical to 9ae2934;\n- the workflow blob at 5eea6e2 is byte-identical to f63f6c4;\n- the workflow blob at accepted 9ae2934 was byte-identical to its former base 4e79554.\n\nTherefore the exact product source and four-boundary Security acceptance recorded in #764 (comment) carry forward unchanged. The only delta is the separately reviewed/merged #767 CI memory-and-diagnostics change.\n\nThis is exact-source re-ack only. The current final hosted matrix remains in progress; merge/release/installed-artifact claims still require its successful completion. No Rust build or local runtime was run on the lab host.

On 5eea6e2 the workflow-import corpus differed at conflict_native_run:
the probe renames a bundle's run to an existing native run, and published
PHP answers target.run_id_conflict, but native's reference fence ran inside
eligibility and answered the bundle's commands' resolved runs first. An
ineligible bundle (identity_missing) would likewise have gained reference
findings PHP never reports.

The fence now runs after eligibility and the existing-run check, and before
a dry run or a write, so every answer PHP gives stays PHP's and a crafted
bundle is still refused before anything is written, dry runs included. A new
test pins that order on each backend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security re-review of exact head ce065ab (parent 5eea6e2): the source delta is accepted with no new source blocker.

The change restores the published ordering: base eligibility failures return before native-only reference findings; an existing run returns the published run_id_conflict before those findings; otherwise the defensive reference fence still runs before either dry-run success or any write. The new test pins each boundary. The patch is limited to that reordering/helper and its regression test, and git diff --check passes.

I did not run Rust builds or tests. Merge acceptance remains gated on the exact-head hosted matrix. At this receipt, 14 checks are complete without failure and 41 cross-database/corpus checks are still in progress; do not treat this source acceptance as substituting for those required lanes.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security final exact-head acceptance for ce065ab4b3e3659cf3c6d068ff54fe09c66516d3.

The previously reviewed ordering correction remains unchanged: base eligibility failures return before native-reference findings, the existing-run conflict retains the published target.run_id_conflict result, and the native reference fence still runs before either dry-run success or mutation. The added regression covers those three outcomes.

Hosted exact-head evidence is now terminal:

  • 58 PR checks completed: 57 successful and 1 intentional skip;
  • no failed, cancelled, or pending check remains;
  • the expanded execution/codec, PostgreSQL, MySQL/MariaDB, published-SDK adapter, repository-contract, public-boundary, analysis, and Sonar lanes all completed for this head;
  • GitHub reports the PR merge state clean.

Disposition: accepted for this exact head. This supersedes my earlier conditional source-only receipt. Any successor commit requires fresh qualification/review. I did not run Rust builds or tests on the lab host or the Rust VPS and made no runtime, credential, service, or production change.

@rmcdaniel
rmcdaniel merged commit 2dd58d2 into main Oct 25, 2026
58 checks passed
@rmcdaniel
rmcdaniel deleted the rust-325-workflow-import branch October 25, 2026 22:16
@rmcdaniel

Copy link
Copy Markdown
Member Author

Merged as 2dd58d25d3dfa64221e80bf62308150630e3ee95, pinned to the Security-accepted exact head ce065ab4b3e3659cf3c6d068ff54fe09c66516d3 (#764 (comment)).

  • Parents: f63f6c4f (main) and ce065ab4b. Merge tree ce21cf5d3d44 equals the head tree, so main now holds exactly the qualified source.
  • Before merge: 56 checks passed with 1 intentional skip, merge state clean, and SonarCloud showed 0 open issues with the quality gate OK.
  • Branch rust-325-workflow-import deleted.

Next in #325: the waterline import (wl1) merges this main and activates as the next single PR.

rmcdaniel added a commit that referenced this pull request Oct 25, 2026
…-record-local-activity

# Conflicts:
#	.github/workflows/server-parity.yml
rmcdaniel added a commit that referenced this pull request Oct 26, 2026
…st-325-cancellation-scopes

# Conflicts:
#	.github/workflows/server-parity.yml
#	docs/rust-server-port.md
rmcdaniel added a commit that referenced this pull request Oct 26, 2026
…st-325-nexus-operations

# Conflicts:
#	.github/workflows/server-parity.yml
#	docs/rust-server-port.md
#	rust/src/runtime/execution.rs
#	rust/tests/fixtures/unserved-php-routes.v2.11.1.txt
rmcdaniel added a commit that referenced this pull request Oct 26, 2026
…nto rust-325-workflow-stream-writes

The port guide now counts 142 served route methods: stream writes and the
two workflow imports each add two to the base 138.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rmcdaniel added a commit that referenced this pull request Oct 26, 2026
…ust-325-bridge-adapters

Conflicts kept both sides: the router, delegates, modules, parity contract,
probe and workflow test list carry bridge adapters with the workflow
imports and record_local_activity. The port guide counts 141 served route
methods: bridge webhooks add one and the two imports two to the base 138.

Co-Authored-By: Claude Opus 5.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