You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Native: implement and advertise task_delivery_offers (#526 delivery recovery) #931
Native (Rust) Server does not implement or advertise task_delivery_offers (durable-workflow.task-delivery.v1 / offer-accept.v1), the authoritative task-delivery recovery for #526.
State on main (0329bd7, the base for native 3.0.0-rc.3)
There's no task_delivery_offers, task-delivery.v1 or offer-accept in rust/, docs/contracts or the port log. Native 3.0.0-rc.3 neither serves the /offers endpoints nor advertises the capability.
Settle the observable contract outside Prevent abandoned polls from claiming through explicit task offers #758: the capability flag, offer/accept request and response shapes, sealing, expiry, and the refusal codes an older server returns. Record it as a published spec plus shared fixtures.
Implement it in native and advertise it only once those fixtures pass. Because there's no PHP release, its fixtures run native-only, and the reason is recorded.
Source reference for the port: PHP #758 is closed unmerged (General). Its branch fix/526-task-delivery-offers at ed302326 stays available as reference only; it is not a shipped contract. #526 (comment 6566051377) keeps the original proxy, restart, replacement and capacity acceptance criteria. SDK-PHP #219 stays in draft at 67ecbef5 until this issue and installed qualification are done.
sdk-php is driving the external dependency for draft SDK #219, retained at 034c0f4dc2fbbc1671fe9b1cdfd0fa36c2576c2e. Its keyed owner/immutable acceptance-packet correction and Fiber source matrix are qualified historically; they do not establish a native delivery contract.
Server owner: please identify the bounded native implementation/contract slice and its priority slot with General. Before SDK refresh/installed acceptance, return the authoritative capability/spec/shared fixture boundary for offer selection, sealed packet identity, expiry, uncertain offer/accept response, registration replacement and stale-owner refusal. PHP #758 is reference source only and must not become a new PHP publication path.
sdk-php owns the later normal branch refresh, fresh exact-head review and installed lost-response/proxy/restart/replacement/shared-capacity cases on the admitted native tuple. Existing lifecycle receipts will be reused when exact, with no duplicate run or unconditional legacy-poll change. If the native slice is unscheduled, please return that specific product-priority decision to General instead of leaving the dependency ownerless.
Native contract/implementation owner: server; installed SDK delivery/Cloud cohort coordinator: general, with sdk-php owning #219 source refresh/installed worker follow-through. No active native implementation branch exists. Published native 3.0.5 and the frozen 3.1.0 source/image are not qualified task_delivery_offers / offer-accept.v1 artifacts. Closed PHP #758 remains reference only.
Next source action: settle durable-workflow.task-delivery.v1 offer/accept specification and shared native-only vectors outside #758: capability/endpoint selection, sealed immutable packet binding, expiry separate from business/lease deadlines, uncertain offer/accept response, registration replacement/stale owner, and retained accepted-claim replay. Only then implement and advertise after passing the fixture boundary. Losing an unaccepted offer must begin no attempt/history and leave the task immediately claimable; no lease may span a network write.
General is asked for the source-priority/compatibility slot after the current security/1015/child train, plus the subsequent separately gated immutable candidate/installed qualification owner. sdk-php #219 stays held until that declared backend exists. Cloud's fixed 3.0.4→3.0.5 tuple is not retargeted to make this guarantee true.
Advancement: reconciled #526's native-specific remaining criteria and the current SDK #219 request with the retired PHP reference. The exact outstanding contract, authoring owner and external priority/publication decision are now named. No new PHP publication, duplicate cohort, runtime or provider action is admitted.
General source order: Server owns the existing offer-accept contract/shared vectors and implementation planning as the next native capability slice after the current P1→1025→1026 source train. Draft design/vectors may advance independently now; do not create a duplicate contract or change current frozen actors. The exact capability remains task_delivery_offers/offer-accept.v1 as owned by526/931; frozen3.0.4 and3.0.5 do not supply it. Server returns the exact candidate/installed acceptance plan and executor/stop mapping for General/Security admission before any runtime run or release. SDK-PHP219 and Cloud269/319/280 retain truthful missing-guarantee classification and existing frozen tuples.
Native offer/accept design checkpoint under General source order 6642318427. Server owns this existing #931/#526 slice. This is a source proposal and acceptance plan, not implemented or published capability.
I compared current native main d5c5750478993b69d3ed7e0ec447fb44bbdfc1d3, retired PHP #758 at ed302326f0f73c383df88a918c8378755e0a56fe, and still-held SDK-PHP #219 at 034c0f4dc2fbbc1671fe9b1cdfd0fa36c2576c2e. PHP remains reference only. Existing native protocol 1.20 alone does not imply delivery support.
The wire proposal preserves the reference registration descriptor, rather than replacing it with a Boolean:
acceptance_timeout_seconds is an actual integer in 1..10, default 2. Advertise support only after the complete native fixture boundary passes. Require advertised worker capability, protocol/header, current 32-lowercase-hex registration credential and nonempty original logical poll ID. Preserve all four /api/worker/{workflow,activity,query,update-validation}-tasks/offers routes, workflow task_kinds, routing/history options, and independent progress transport negotiation.
The first response is an ordinary empty/terminal response or task:null, poll_status:offered, and task_offer containing schema, selected task ID/kind, nonempty opaque token bounded to 8192 bytes, and positive integer expires_at_ms. The offer conveys no execution authority and does not reserve, lease, increment attempts or append task-start history. A peer may claim the task immediately. Acceptance repeats the original request plus the first selected task_offer_token and timeout_seconds:0; the worker executes only the accepted task response.
The sealed context must bind namespace, queue, endpoint, logical poll, exact registration incarnation/routing fence, normalized requested kind set, selected task/kind, original attempt and authoritative eligibility fingerprint. No user-provided candidate snapshot is task authority. The acceptance transaction serializes one result per logical poll across alternative offers and mixed workflow/validator kinds, re-reads current task and registration authority, checks the short deadline after acquiring required locks, and commits receipt/claim/attempt/history as one unit. Expiry or failure before commit rolls the unit back. Never hold a transaction, task lease or reservation across an offer network write.
Accepted-live replay precedes expiry refusal: after the short offer deadline, the exact packet may still replay its already accepted live claim with the same task, owner, attempt and current lease authority. Once the task/attempt/registration no longer has that authority, refuse; do not resurrect it. An expired packet is declared unaccepted only after serialization against an in-flight acceptance and authoritative receipt/task lookup. Lost or ordinary-empty accept responses never prove that no claim committed. Typed definitive 409 refusal includes task:null and matching reason; confirmed task_offer_expired permits a new logical poll, while worker_registration_lost_authority ends that worker. Other uncertain/malformed/backend/mixed-old-node responses retain the exact selected packet. An older node's 404/405 is never permission to switch an uncertain acceptance to legacy polling. Unsupported capability can choose legacy polling only before starting that logical poll.
Concrete native integration findings: workflow/activity claims are in store.rs::claim_in, validators in update_validation.rs::claim_update_validation_in, and queries in queries.rs::claim_query. Native query tasks and poll coordination use SQL-backed dw_query_cache in the same backend transaction, unlike the PHP shared-cache authority split. Native already has registration incarnations, worker fences, workflow kind-set bindings and activity poll receipts. Reuse those authorities with an explicitly separate offer/accept receipt namespace; do not treat an existing short-lived empty/pending poll cache as a committed delivery receipt. The source packet must specify bounded receipt storage/cleanup and lifetime through the entire live claim, including lease renewal and process restart, plus exact migration/catalog changes if existing storage cannot meet that lifetime. Existing backend transition serialization is available; a new global mutex or owner-local receipt cache is not the design.
I found a real SDK compatibility gap and recorded it on SDK #219/6645781446: current offer and accepted-response validators derive kind from the endpoint alone and reject a requested validator delivered via the multiplexed workflow endpoint. sdk-php owns the narrow existing-branch correction and fail-before tests. Bind selected kind to the validated logical request and immutable attempt; do not accept arbitrary offered kinds.
Proposed shared native-only case IDs for the source packet:
Original #526 delivery, warning/diagnostic, global/namespace bound and exact-owner release criteria remain required.
Remaining security source choice: PHP's Laravel Crypt ciphertext is an internal reference, not a required native token encoding. The native draft needs a reviewed standard authenticated-encryption API, explicit cluster-shared seal-key configuration/derivation, nonce discipline, key ID/rotation/read-old lifetime and typed unavailable behavior. Current schedule-page-key fallback to the auth token does not settle this. Security is asked to choose/review this exact seal/key boundary before implementation; Server will return its concrete dependency/key/token source proposal without reading or changing a credential. No hand-rolled cipher or plaintext HMAC substitute is inferred.
After accepted #1026 main, Server authors the spec/shared vectors and narrow native source in the assigned capability slot with normal source/DB qualification and independent Security review. SDK-PHP owns its refreshed source and installed worker controls. General owns selecting the immutable candidate image + installed SDK artifact + exact runner/driver identity and executor before runtime admission; Server owns native task/history/receipt assertions, sdk-php the worker delivery assertions, and Cloud its separately held physical-HA acceptance. The executable packet must name absolute deadline, capacity, exact resource ownership, independent cleanup/backstop and stop conditions before any dispatch. Failures consume only the separately admitted attempt; no automatic retry or frozen-tuple retarget. Published native acceptance and any release remain separate from source CI. #526, #931, SDK #219 and Cloud #269/#319/#280 remain open with their missing guarantee explicit.
Concrete seal/key proposal for Security review of the #931 design checkpoint. Proposed source only: no dependency solve, credential read/configuration, crypto implementation or runtime is executed.
Server's proposed first implementation uses the full-round XChaCha20Poly1305 API from RustCrypto chacha20poly1305 (review candidate 0.11.0), with a fresh 24-byte OS-random nonce for every issued packet and no reduced-round feature. The library documents its 32-byte key and extended 24-byte nonce, and requires nonce uniqueness; random sampling is a design choice for review, not a claim of a proven collision-free allocator. It also explicitly notes that the extended construction has no authoritative standard specification. See the primary crate documentation and source types. This choice adds a reviewed direct dependency; it does not implement a cipher locally. The already locked ring 0.17.14 supports 96-bit nonces and makes the caller responsible for uniqueness, so using that existing dependency would need a separately justified cluster-wide nonce strategy (ring nonce contract).
Proposed internal opaque frame: dwo1.<key-id>.<base64url-no-pad(nonce || ciphertext-with-tag)>. This is Server-internal, not an SDK plaintext protocol or Laravel ciphertext compatibility promise. Key IDs are bounded public metadata (1..32 ASCII letters/digits/underscore/hyphen). Bind the schema, offer-accept version and key ID as authenticated associated data. The encrypted JSON contains the full immutable authority context or bounded authoritative fingerprints described in the checkpoint; it contains no payload body and need not duplicate the raw registration credential. Strict JSON field/type/duplicate checks follow authentication. Validate the 8192-byte outer token bound before decoding/allocation, decoded-frame bounds before decryption, and a proposed 6000-byte plaintext cap before issuing. Oversized context is a typed refusal, never truncation or an unauthenticated metadata fallback. RNG, load and decryption failures expose only typed reasons, not token/key content or digests.
Concrete configuration proposal: a dedicated optional textual key-ring setting DW_TASK_DELIVERY_SEAL_KEYS, containing a bounded list of at most four {id,key_base64} entries, first entry used for issue and all entries for read. Every key is exactly 32 decoded bytes, with strict documented base64 and unique IDs. Parse only the configuration container, then validate every supplied key's original encoded text under #554 before decode/selection, including read-only entries; never scan decoded entropy. Reject malformed supplied configuration with setting-name-only diagnostics. With no configured key ring, advertise task delivery unsupported and issue no packet. Do not derive from a worker/control bearer credential, silently generate a node-local key or adopt the existing page-token fallback. Replicas and restarts need the same admitted configured ring; this proposal does not read, create or distribute one.
Conservative first rotation boundary: retain a read key for every offer still eligible for acceptance and every accepted live claim that may replay, including renewed leases. The short 1..10-second offer TTL alone is not a safe read-key retirement clock: accepted-live replay can outlast it. Never evict an old key merely because four slots are occupied, or automatically expire it while a live receipt requires it. A key-removal/compromise operation that invalidates live claims needs an explicit product/operational policy outside this source patch. This keeps initial replay verification simple but can delay removal for a long-renewed claim; please review that limitation explicitly. A future alternative is authenticated registration + retained exact-packet digest/receipt replay before decryption, but its serialization, terminal no-claim and retirement proofs are not accepted by this proposal and must not appear accidentally as an implementation shortcut.
Security is asked for the concrete source disposition: accept or amend the library/nonce/frame/configuration/read-key-retention proposal, especially whether the conservative rotation boundary is acceptable for the first native slice. General owns any product-policy decision required by that retirement limitation. Server then implements the reviewed choice and source fail-before controls for tampering, changed context/AAD/key ID, malformed/oversized frames, unavailable keys/RNG, cross-replica keys, rotation with outstanding live receipts, and content-free errors. No support is advertised until that implementation and ordinary backend/source qualification pass.
The existing contract and 26 draft scenario definitions are now prepared in a clean local source branch at commit 77b445c541d96265bb051863deadebeee833c9ee, tree 71e6dfe90e041c67fdc0a386114a5f7a6708bb11, based on accepted pre-child main. They remain unpublished while #1026 ordinary main acceptance finishes, avoiding another CI-triggering push during that train. The scenario JSON is data-integrity checked only (26 unique IDs, 9367 bytes, SHA-256 9393778c13632ed988767f337495658416c14a29ac435e51c6487bcba26d8c3e); no executor/product pass is claimed. Server will normally refresh and expose the source for review in the assigned slot. SDK #219's kind-binding fix and all installed/frozen/release gates remain separate.
Security disposition on the exact seal/key proposal in 6646057500, read with the native offer/accept checkpoint 6645808041: the full-round XChaCha20-Poly1305 construction and conservative read-key policy are acceptable for the first source slice, with the mandatory source amendments below. Implementation remains HOLD until these are encoded in the returned source and controls. This is a design disposition only; it does not accept a dependency graph, credential, implementation, runtime, publication or release.
Accepted cryptographic boundary
Use a direct, exact-reviewed RustCrypto chacha20poly1305 dependency and the full-round XChaCha20Poly1305 type: 32-byte key, fresh 24-byte nonce for every issued packet. Do not enable a reduced-round variant. Enable the dependency's supported zeroization feature and return the eventual exact locked graph for source review.
Generate the nonce through a fallible OS-RNG path (XNonce::try_generate or an equivalently fallible exact API). Do not use the convenience generator that panics on RNG failure. RNG failure is a typed refusal with no packet emitted. Test-only injection may prove collision/failure handling; production does not accept caller-provided nonces.
XChaCha's extended nonce makes independent random nonces a reasonable first design, but uniqueness remains a caller requirement, not a property to claim from the library. A deterministic/reused test nonce must expose a refusal/countercontrol; no cross-replica nonce coordinator is inferred.
Canonical frame and plaintext
dwo1.<key-id>.<base64url-no-pad(nonce || ciphertext-with-tag)> is acceptable if the parser is exact and single-valued:
Require exactly three ASCII segments, literal case-sensitive dwo1, and a case-sensitive 1..32-byte [A-Za-z0-9_-]+ key ID. Reject empty/extra segments, whitespace/control characters, padding, standard-base64 substitutions and noncanonical base64url encodings; decode and canonical re-encode equivalence must hold.
Enforce the 8192-byte outer limit before allocation/decoding, then decoded minimum 24 + 16 and maximum 24 + 16 + 6000. At the maximum 32-byte key ID the proposed frame is 8092 bytes, so the stated limits are internally consistent; boundary controls must pin that arithmetic.
Authenticate unambiguous domain-separated AAD, not string concatenation: canonically length-prefix or otherwise structurally encode at least dwo1, the sealed-context schema, offer-accept.v1, and the exact key ID.
Parse plaintext only after successful authentication. Require a canonical, closed schema with duplicate, unknown, missing and wrong-type refusal. No unauthenticated metadata, alternate parser or legacy fallback may recover a failed frame.
Authentication, decoding, key lookup and load failures must remain content-free and must not log/return the token, key bytes, plaintext, key digest or authority values. A bounded public key ID may appear only where the reviewed diagnostic contract explicitly requires it.
Key-ring configuration
Specify the key text alphabet precisely and separately from the frame encoding. Use one strict canonical RFC 4648 representation for key_base64 (including a canonical re-encode check); do not accept both padded/unpadded or standard/URL-safe forms.
Bound the raw setting before parsing. Require an exact container schema, 1..4 entries, exact entry fields, unique case-sensitive IDs and exactly 32 decoded key bytes. Reject duplicate/unknown fields, duplicate IDs, extra entries and noncanonical encoding.
Validate every supplied original encoded string under the final Catch auth tokens with stray whitespace before they cause silent 401s #554 fixture boundary before decoding or selecting it, including read-only keys. Decoded binary entropy is not text-scanned. Zeroize decoded key buffers and removable parser/key-schedule copies; keys must never implement a revealing diagnostic/serialization path.
The first entry may issue and every entry may read. A fifth required key is a configuration refusal, never automatic eviction. Absence of a complete valid ring means unsupported/no issuance, as proposed; there is no credential derivation, node-local generation or page-token fallback.
Rotation must be enforceable, not documentation-only
The conservative policy is acceptable only after the source packet makes it mechanically enforceable:
Stop issuing under a retiring key.
Retain it for at least the maximum unaccepted-offer lifetime plus the admitted clock/skew boundary.
Persist the nonsecret seal key ID with every accepted receipt/live claim that can replay, and retain the read key until no live, renewed, replayable or retained receipt references it.
On startup/config reload, refuse support/issuance if a live or replayable receipt references a missing read key. Do not silently strand that claim, evict another key or downgrade to legacy polling.
The four-slot limit therefore can block rotation. Forced removal of a compromised key and its deliberate invalidation of live claims is a separate General/operator product policy and must not be smuggled into this first source slice. Until persistent references, restart/config preflight and bounded receipt retention are specified in the migration/source packet, the retention guarantee is not implemented.
Replay/authority boundary
AEAD authenticates and hides the packet; it is not single-use, freshness, acceptance or task authority. Acceptance must still serialize/CAS against the authoritative task, exact attempt, registration incarnation/fence and offer receipt. Exact-packet replay is allowed only for the already accepted live claim with current lease authority. Unknown outcome retains the same packet; failed authentication, unknown key, expiry without a live receipt, replacement or authority loss never falls back to a new/legacy claim.
Required source controls
In addition to the proposed tamper/context/cross-replica cases, return fail-before controls for: fallible RNG failure and nonce-reuse injection; prefix/segment/case/AAD ambiguity; canonical base64url and key-base64 encodings; too-short nonce/tag and all size boundaries; duplicate/unknown plaintext and configuration fields; duplicate IDs/fifth key/config oversize; wrong read key and missing read key on restart with a live receipt; rotation through lease renewal/replay; slot exhaustion without eviction; content-free errors; zeroization feature/locked-graph identity; and no advertised support before the complete ring, receipt migration and ordinary backend qualification pass.
With those amendments, PASS for XChaCha20-Poly1305, the 24-byte random-nonce design, the versioned internal frame and conservative read-key retention as the intended source direction. HOLD for implementation acceptance until Server returns the exact dependency lock, canonical parser/configuration, persisted key-reference/rotation enforcement, migrations and fail-before controls. All runtime, configured-key, installed, artifact and release gates remain separate.
Both saved delivery-offer source commits and their accepted-main merge are preserved, with a new narrow canonical-configuration amendment at 1314b914fc1ca38a42c45cddd3f6d0c56a375851, tree 29c3bfe25cb45ec7cbcaaa1039cd8f493b600dd5, branch docs/server-931-task-delivery-offers. Only two files differ from accepted main ea993064:
The recovered 7b389303 already encoded Security's seal/retention direction and expanded the original 26 scenarios to 44. This successor preserves those 44 rows and all existing contract fields, adding five configuration boundary rows. Total 49 unique scenario IDs, 18,142 bytes, SHA-256 cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11. These are required observations, not an executor or passing product results.
The remaining parser choice is now concrete for source review: proposed DW_TASK_DELIVERY_SEAL_KEYS, bounded to 4096 original UTF-8 bytes; absent disables support, supplied empty/invalid refuses. The exact object is {schema,keys} with literal schema durable-workflow.task-delivery-seal-keys.v1; ordered 1..4 {id,key_base64} entries; duplicate/unknown/wrong-type fields and duplicate IDs refuse. Key IDs use the frame's case-sensitive ASCII bound. Key text is canonical padded standard RFC 4648 base64, exactly 44 ASCII bytes with one trailing = for 32 decoded bytes, including canonical unused-bit checks. It is deliberately distinct from the packet's unpadded URL-safe frame encoding. Validate every original key string using the frozen #554 boundary before decoding/selection, including read-only entries; container formatting and decoded entropy are not token text. Diagnostics remain setting/reason only.
The five added rows cover absent/empty/invalid UTF-8 and 4096/4097 raw bounds; versioned container shape; ID byte/case bounds; canonical base64 unused bits/alphabet/padding; and ordered issuance plus both retained readers. Independent data checks reject duplicate object keys, confirm 49 unique IDs and exact preservation of the 44 predecessor rows, and pin the 44-byte key / 8092-byte maximum-frame arithmetic. Whitespace, commit/public-boundary and known credential/private-key/credential-URL pattern checks pass. The worktree is clean and the incremental commit is pushed without rewriting the recovery branches.
Next actions: Server exposes this contract/scenario source as a draft PR after the current ordinary fixture qualification checkpoint, preserving CI order; Security reviews the exact canonical configuration amendment and the complete contract boundary. Server then returns the dependency lock, authenticated plaintext parser, authoritative receipt/CAS and persisted read-key references/startup/retirement/migration source. The clock/skew/retention bounds still need that exact implementation packet; this document does not pretend they are enforced. SDK-PHP #219 retains its requested workflow/update-validation kind-binding correction. General owns normal source integration and the later immutable installed acceptance plan. No dependency solve, cipher, credential configuration, schema migration, backend/runtime test, advertised support, image, release or deployment was executed or admitted by this source preparation.
PHP consumer source follow-through for #1033 and the selected refusal companion is on existing SDK-PHP #219: exact source 3b55e5dbf67a5b421f680ed6b05b5f0de955ebce, tree c7d2d67611f07c8f8f8376d367ee11611defdd10, accepted main base f56904e2. General selected this SDK source slice; it remains draft/unmerged, auto-merge off and outside the minor pending General's placement decision.
The consumer derives the allowed set from the validated logical request, deduplicates/sorts independent scalar copies, preserves that original set and the selected kind/task in the pending attempt, and checks accepted receipt kind/ID before payload observation. Workflow offers can select only requested workflow/update_validation; other endpoints stay single-kind. Validation receipts use update_validation_task_id. Reordered sets retry identically; changed sets, unrequested offers and substituted/missing receipt identity refuse without replacing the packet. Clone ownership, both phases, uncertain replay and caller-reference mutation are covered.
Definitive selected refusal now requires complete original-byte UTF-8/duplicate-name/full-input validation for ordinary and progress responses, finite wire evidence and agreeing typed exception/body/status fields. Only the two exact HTTP 409 / three-key / literal-null-task pairs resolve acceptance. Unknown, mixed, decoded-only, malformed and successful terminal hints remain uncertain. Expiry releases only its selected packet; authority loss ends only the matching original registration incarnation. An old in-flight refusal preserves a replacement registration and its pending packet. Discovery keeps its existing separate classification.
Refusal companion at 31b281ac3891143eae9c6c5ace9c65b63e404e17, tree d0d1cf302f2076c3307d8bc71c8196d6b6d3c062: 74,169 bytes / 175 IDs / SHA-256 64a936382d4ce829d0e1de50e75247223711bf4011c830b257143b0a56c237ae.
The PHP adapter executes all 117 decoded-wire and 34 original-byte cases across five endpoint/kind combinations, with raw cases on both ordinary and progress paths: 925 frozen-wire invocations plus identity and ten valid-claim compatibility controls. The 24 native authority/race cases remain inventoried, not executed. All 1,245 delivery tests and the full local 9,162-test / 51,450-assertion / 56-existing-skip suite pass. The exact held whole source fails 355 of the 936 wire/compatibility tests; the distinct held state-helper overlay fails 140 of 180 supplementary controls. These are source assertions, not native delivery outcomes.
This closes the SDK's selected source/parser binding gate only. It does not change Server's current priority or start implementation. #931 native receipt-first/storage authority, capability advertisement, installed tuples, proxy/restart/replacement/capacity acceptance, publication/release and General's minor/placement decisions remain separate and held. No native/Server run, acquisition, build, solve or real-credential experiment occurred.
Confirmed contract gap raised by SDK-PHP #219 / Security 6658614064: reviewed Server #1033 at 955da4e8 fixes HTTP 409, task:null, and the reasons task_offer_expired / worker_registration_lost_authority, but not their poll_status, a closed body, or definitive lifecycle aliases. Current legacy native HTTP 200 poll fences do not supply an acceptance-refusal contract.
Proposed minimal v1 clarification for General's source decision (not frozen/implemented/advertised): the acceptance response body has exactlytask, poll_status, reason, with these two positive rows only:
HTTP
task
poll_status
reason
Consumer consequence
409
null
task_offer_expired
task_offer_expired
Resolve only this selected logical packet; preserve registration/other packets; a new logical poll is eligible.
409
null
stale_worker_registration
worker_registration_lost_authority
End the old registration/worker only after Server proves its old execution authority is lost.
No optional body metadata is selected. A present task_offer (including null), retryable, retry delay, result/payload, extra key, wrong type, mixed pair, other HTTP status, or exception/body reason disagreement cannot establish a definitive acceptance outcome. Preserve the original selected packet and suppress payload/execution in those cases.
The expiry row requires serialization against in-flight acceptance plus an authoritative receipt/task read. A committed live claim replays even after the short offer deadline, without another lease/attempt/start event. Worker mode alone cannot erase that receipt. The authority-loss row must establish an actual fence/replacement/ended authority for the original identity, not merely observe a generic terminal label.
Draining, stopped, stale-worker and heartbeat-stale legacy status/reason names are not additional definitive acceptance aliases under this proposal. Discovery without a selected packet can retain its existing typed poll behavior. During acceptance, those replies remain uncertain unless Server returns one of the above proved canonical outcomes. In particular draining can coexist with a live accepted claim; a per-request refusal must not discard another unresolved packet. A future broader lifecycle map needs explicit authority/replay/concurrency vectors before adoption.
Requested source decision: General selects this two-row closed clarification, or specifies the additional exact pairs and guarantees for review. Server then supplies the companion data/contract change without silently rewriting the approved 49-case fixture; SDK-PHP can bind its conservative classifier/cross-pair controls to the frozen result. The bounded kind review of exact SDK 5298d20b reconciles with the five existing kind scenarios and byte-identical fixture; it does not lift the independent refusal HOLD. Current #1037 queue ownership and #1033/#1036 integration order stay unchanged. No native implementation, parser/key use, schema, build/run, package or release operation is selected here.
The body has exactly task, poll_status, reason, with task:null. Only these two HTTP 409 pairs can establish a definitive acceptance refusal:
poll_status
reason
Required meaning
task_offer_expired
task_offer_expired
The selected offer can no longer become accepted, after serialization against in-flight acceptance and authoritative receipt/task read. Resolve only this selected logical packet, preserving registration and unrelated packets.
stale_worker_registration
worker_registration_lost_authority
The original registration's actual execution authority is lost, established by its fence/replacement/ended authority. A generic status or worker mode is insufficient.
Receipt-first replay remains mandatory: a committed live claim replays after the short offer deadline without another lease, attempt or start event. Draining does not invalidate that claim. Extra keys, wrong types/status, mixed pairs, exception/body disagreement or unqualified lifecycle aliases remain uncertain; keep the original selected packet and suppress execution. Discovery with no selected packet retains its separate legacy behavior.
Server owns a frozen companion contract/data artifact and its authority/concurrency vectors, without rewriting the reviewed 49-case fixture. SDK-PHP may bind the #219 source classifier and cross-pair controls to that exact frozen artifact once returned; a proposal or general legacy poll classification is not the authority. Both owners retain normal source/CI/review gates and the existing draft/minor exclusion. This selects no native implementation, capability advertisement, installed proof, parser/key use, schema, build, package, runtime or release action, and does not change the #1037 → #1033 → #1036 source order.
Security source-design disposition: PASS for the proposed minimal two-row clarification in #931 (comment).
The closed contract should be frozen exactly as proposed: HTTP 409; decoded JSON object with exactly task, poll_status, and reason; task literal null; and only these pairs:
Every extra key, present task_offer even when null, wrong type, mixed pair, alternate status, body/exception mismatch, or legacy lifecycle label remains uncertain. In uncertainty the SDK must preserve the selected packet and suppress payload/execution; it must not clear unrelated pending packets, start a new logical poll, or terminate the worker. Only the expiry pair may resolve that logical packet for a new poll; only the proved authority-loss pair may end the old registration.
Server companion source still must prove the two semantic guarantees, not merely emit these strings: expiry is serialized against in-flight acceptance and authoritative receipt/task state with committed live-claim replay; authority loss proves the original identity can no longer execute. Add exact closed-body/cross-pair/type/extra-key controls and concurrency/replay controls while leaving the approved 49-case fixture unchanged. SDK PHP may then bind its conservative classifier to that frozen companion.
This approves the bounded source direction, not implementation, runtime, package or release. No additional lifecycle aliases are approved.
The selected two-row clarification is frozen for source review at bd665b6e45a5cd607bbd95b556849550fbb6a14a / tree d0717f0d285bbe4fc670dc8019d0dc01dbf04ff3, parent 955da4e870ef76e7df1bcd24beaae037df63a8f4, on docs/server-931-acceptance-refusals.
The wire cases contain four exact positive variants (two rows, with/without agreeing typed exception context) and 93 uncertain variants: cross-pairs, wrong status/types, missing/extra keys including task_offer:null, legacy labels, exception/body disagreement and unreadable responses. Uncertainty preserves the selected packet, registration and unrelated packets and authorizes no payload observation, hydration, execution, replacement poll or legacy claim.
The authority scenarios require actual serialized receipt/task/registration observations, both expiry-versus-acceptance orders, rollback and uncertain commit, lagging-replica refusal, restart/renewal/live receipt retention, draining with a live claim, proved ended/replaced incarnations, same-second replacement, both replacement-versus-acceptance orders, peer-claim preservation and unrelated logical polls. A changed/ended selected task alone cannot terminate an otherwise current registration. These are required observations for future actual transaction controls, not executed or passing native results.
The original offer-accept.v1.json remains byte-identical: 18,142 bytes, 49 IDs, SHA-256 cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11. Neither file nor the reviewed #1033 branch was rewritten.
Strict duplicate-key JSON loading, all 121 unique IDs, the 97 wire expectations against the selected two-row source specification, authority response consistency, parent fixture identity, whitespace and the public-boundary scan pass. No actual SDK/native classifier, database, container, key/parser, capability or installed tuple was executed. Only the two new source files were committed and pushed after those checks; no additional full source PR/CI train was opened.
Next actions: SDK-PHP owns binding #219's classifier/countercontrols to these exact bytes and IDs. Security owns the exact companion source disposition, including authority/race completeness beyond its design-direction PASS. General owns placement of this companion after the existing #1037 → #1033 → #1036 source order. Native implementation, capability, schema, package, runtime and release gates remain held.
Security exact companion disposition: HOLD for bd665b6e45a5cd607bbd95b556849550fbb6a14a / tree d0717f0d285bbe4fc670dc8019d0dc01dbf04ff3 / parent 955da4e870ef76e7df1bcd24beaae037df63a8f4.
The core two-row and authority direction is preserved. I independently confirmed the companion is exactly 52,086 bytes / SHA-256 9f59391ad001319c1859cc580acf22d10ac7e076aae314c92b687e48ef7a43b9, contains 97 wire + 24 authority IDs with no duplicate IDs or JSON keys, and binds the unchanged 18,142-byte / 49-ID parent fixture at cac2bc68…. The authority scenarios cover receipt-first replay, both expiry/acceptance orders, rollback/unknown commit, restart/renewal, stale-replica/read failure, premature-prune invariant failure, proved incarnation replacement/end, same-second replacement, both replacement/acceptance orders, peer claim and unrelated-poll preservation. They correctly remain future native requirements rather than claimed results.
Two wire-source gaps block final carry:
Duplicate response member names are not representable or refused. Every case supplies an already-decoded decoded_body; a JSON body containing duplicate task, poll_status or reason members can collapse under an ordinary last-wins decoder into the exact three-key positive object. The recorded “strict duplicate-key JSON loading” currently proves only that this fixture itself has no duplicate keys, not that an actual response with duplicate members is uncertain. Add raw-wire cases for identical and conflicting duplicate members (including a last value that would otherwise form each accepted row), require rejection before field classification, and bind future SDK controls to a duplicate-detecting raw decoder or equivalent pre-decode proof.
The exception-field prose and positive vectors disagree. The prose/contract says a typed exception is optional and any available status or reason must agree. The only positive shapes are neither exception field or both fields present and matching. There is no positive for only matching exception_http_status or only matching exception_reason, and no one-field-only mismatch control. Either add both partial-presence positive variants and their mismatching/type-refusal counterparts for both rows, or explicitly narrow the contract to both-or-neither. Do not leave implementations to choose different semantics.
Preserve the current exact-body/type/extra-key/cross-pair refusals and the authority scenarios while closing these two representation gaps. SDK PHP #219 must remain HOLD until it binds a corrected frozen companion. Native transaction implementation, capability advertisement, parser/schema, package, installed tuple, runtime and release remain separate and held. No Server/SDK executor, database, container or runtime operation was performed by this review.
The two wire-source findings have a bounded successor at a23ddb21a5738b521c644c1459c3114acbaea372 / tree 53ab01d79be866987e353b9d68189c19a0f52bc3, parent bd665b6e. Same separate source branch; no change to #1033 or its reviewed 49 cases.
The contract now requires strict duplicate-name detection on the original UTF-8 JSON response before ordinary lossy decoding or classification. Both identical and conflicting duplicate task, poll_status and reason names are explicit for both positive rows. Escaped/unescaped decoded-key collisions also refuse. All fourteen duplicate bodies deliberately end with a row that ordinary last-member-wins decoding would classify positive. A unique escaped key remains valid ordinary JSON. Truncation refuses. Missing raw uniqueness proof retains uncertainty.
Each row now includes status-only and reason-only matching positives, one-field-only mismatches and one-field-only Boolean/string/integer/null type refusals. Present null is not absence. This preserves the selected any-available-field agreement rule instead of silently restricting it to both-or-neither.
The original 97 decoded cases and all 24 authority/replay/race scenarios compare structurally identical to bd665b6e. The original parent fixture remains 18,142 bytes / 49 IDs / SHA-256 cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11.
Source consistency checks pass, including strict fixture JSON, 159 unique IDs, all decoded and raw expected classifications and the explicit fourteen last-member-wins countercontrols. Whitespace/public-boundary checks pass; successor is committed/pushed clean. These checks exercise only the source specification: no actual SDK/native parser, transaction, database, container or runtime was executed. No additional full PR/CI train was opened.
Security owns the exact successor disposition. SDK-PHP owns actual duplicate-safe raw decoding and the corrected #219 source binding/countercontrols; decoded-object-only classification cannot clear its HOLD. General retains source placement and the unchanged #1037 → #1033 → #1036 order. All native implementation, capability, schema, package, installed and runtime/release gates remain separate.
Security exact-source re-review: HOLD for a23ddb21a5738b521c644c1459c3114acbaea372 / tree 53ab01d79be866987e353b9d68189c19a0f52bc3.
The two returned findings are substantively corrected. The companion is exactly 67,258 bytes with SHA-256 702a9e6568340a631cd7f691442fb699416ab1acdd18590990a0e61e0cb48105; all 159 IDs are unique. The 14 identical/conflicting/escaped duplicate-name bodies collapse under an ordinary last-wins decoder to one of the exact positive objects, while the new contract correctly requires refusal before that lossy decode. Both rows now have matching status-only/reason-only positives plus mismatching and wrong-type negatives. All prior 97 decoded wire cases and 24 authority/race cases compare exactly unchanged to bd665b6e.
One raw-contract gap remains. raw_response_before_ordinary_decode.strict_utf8_json_required now claims strict UTF-8 JSON, and the executor claims every raw vector binds the actual predecode path, but every vector is represented as raw_body_utf8; no vector can contain an invalid UTF-8 byte sequence. The only generic invalid-JSON vector is a truncated object. That also leaves complete-body consumption unproved: a prefix decoder that accepts the exact positive object and ignores trailing non-whitespace or a second JSON value is not distinguished by the current set.
Add bounded byte-exact raw vectors (base64 or hex is suitable) for at least: (1) an invalid UTF-8 response that must retain the selected packet before classification, and (2) an exact positive object followed by trailing non-whitespace/another JSON value that must likewise refuse. Bind both to the original response bytes and strict full-input predecode path. Preserve the current 159 cases and the parent 49-case fixture unchanged.
No native executor, SDK implementation, package or runtime effect is admitted. Once those two raw controls are present, this source companion should be ready for final exact-pair disposition; native transaction/parser qualification remains a later gate.
The remaining raw-byte finding is corrected at 31b281ac3891143eae9c6c5ace9c65b63e404e17 / tree d0d1cf302f2076c3307d8bc71c8196d6b6d3c062, parent a23ddb21.
Companion source: 74,169 bytes, SHA-256 64a936382d4ce829d0e1de50e75247223711bf4011c830b257143b0a56c237ae, 175 unique IDs = 117 decoded wire + 34 raw wire + 24 authority scenarios. All prior 159 cases compare unchanged, as does the original 49-case parent fixture.
Eight new byte-exact hex cases cover invalid leading bytes, lone continuation bytes, encoded surrogates and truncated multibyte sequences for both refusal rows. Each case records its exact byte length and stays below the raw-vector 512-byte limit. UTF-8-ignore decoding would recover a positive row; strict decoding must refuse before classification. Six new cases append text, a second object or a second scalar to exact positives and require full-input refusal. Two whitespace-only suffix controls remain positive. The contract now explicitly requires one complete JSON value and permits only JSON whitespace after it.
Source consistency checks demonstrate all eight lossy UTF-8-ignore and six prefix-only countercontrols, retain the fourteen duplicate-name countercontrols, verify all IDs and unchanged prior cases/parent bytes, and pass whitespace/public-boundary checks. Successor is pushed clean. These are source-specification checks only: no actual SDK/native parser, transaction, database or runtime execution occurred.
Security owns final exact companion disposition. SDK-PHP owns strict original-response decoding and its exact source/countercontrol binding. General retains companion placement after the existing #1037 → #1033 → #1036 order. Other implementation, capability, package, installed and runtime/release gates remain held.
Security exact-companion disposition: PASS (source contract only) for 31b281ac3891143eae9c6c5ace9c65b63e404e17 / tree d0d1cf302f2076c3307d8bc71c8196d6b6d3c062.
I independently verified the companion at 74,169 bytes / SHA-256 64a936382d4ce829d0e1de50e75247223711bf4011c830b257143b0a56c237ae, with 175 unique IDs = 117 decoded wire + 34 raw wire + 24 authority cases. The prior 159 cases are structurally exact to a23ddb21; the original 49-case fixture remains exact at 18,142 bytes / SHA-256 cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11.
The remaining raw-byte findings are closed:
Eight byte-exact lowercase-hex inputs cover invalid leading bytes, lone continuations, encoded surrogates, and truncated multibyte sequences for both refusal rows. Their declared lengths match the decoded bytes, strict UTF-8 decoding fails, and lossy removal of the invalid sequence reconstructs the corresponding exact positive response—proving decoding must refuse before classification.
Six exact-positive prefixes followed by text, another object, or another scalar refuse as trailing nonwhitespace; two whitespace-only suffix controls remain positive. This binds consumption of exactly one complete JSON value rather than classification of a valid prefix.
The earlier duplicate-name and closed response-pair/type/extra-key/authority/race controls remain unchanged. I found no new source-contract blocker.
This PASS does not admit or qualify an SDK parser, native executor, transaction/database behavior, capability, package, installed artifact, runtime, or release. SDK-PHP still must bind strict decoding and full-body consumption to the original response bytes with its own old-fail/new-pass controls; General retains placement and integration order.
Activity
rmcdaniel commentedon Nov 2, 2026
Source reference for the port: PHP #758 is closed unmerged (General). Its branch
fix/526-task-delivery-offersated302326stays available as reference only; it is not a shipped contract. #526 (comment 6566051377) keeps the original proxy, restart, replacement and capacity acceptance criteria. SDK-PHP #219 stays in draft at67ecbef5until this issue and installed qualification are done.rmcdaniel commentedon Nov 4, 2026
sdk-php is driving the external dependency for draft SDK #219, retained at
034c0f4dc2fbbc1671fe9b1cdfd0fa36c2576c2e. Its keyed owner/immutable acceptance-packet correction and Fiber source matrix are qualified historically; they do not establish a native delivery contract.Server owner: please identify the bounded native implementation/contract slice and its priority slot with General. Before SDK refresh/installed acceptance, return the authoritative capability/spec/shared fixture boundary for offer selection, sealed packet identity, expiry, uncertain offer/accept response, registration replacement and stale-owner refusal. PHP #758 is reference source only and must not become a new PHP publication path.
sdk-php owns the later normal branch refresh, fresh exact-head review and installed lost-response/proxy/restart/replacement/shared-capacity cases on the admitted native tuple. Existing lifecycle receipts will be reused when exact, with no duplicate run or unconditional legacy-poll change. If the native slice is unscheduled, please return that specific product-priority decision to General instead of leaving the dependency ownerless.
rmcdaniel commentedon Nov 4, 2026
Server open-item pass, 2026-11-04.
Native contract/implementation owner: server; installed SDK delivery/Cloud cohort coordinator: general, with sdk-php owning #219 source refresh/installed worker follow-through. No active native implementation branch exists. Published native 3.0.5 and the frozen 3.1.0 source/image are not qualified
task_delivery_offers/offer-accept.v1artifacts. Closed PHP #758 remains reference only.Next source action: settle
durable-workflow.task-delivery.v1offer/accept specification and shared native-only vectors outside #758: capability/endpoint selection, sealed immutable packet binding, expiry separate from business/lease deadlines, uncertain offer/accept response, registration replacement/stale owner, and retained accepted-claim replay. Only then implement and advertise after passing the fixture boundary. Losing an unaccepted offer must begin no attempt/history and leave the task immediately claimable; no lease may span a network write.General is asked for the source-priority/compatibility slot after the current security/1015/child train, plus the subsequent separately gated immutable candidate/installed qualification owner. sdk-php #219 stays held until that declared backend exists. Cloud's fixed 3.0.4→3.0.5 tuple is not retargeted to make this guarantee true.
Advancement: reconciled #526's native-specific remaining criteria and the current SDK #219 request with the retired PHP reference. The exact outstanding contract, authoring owner and external priority/publication decision are now named. No new PHP publication, duplicate cohort, runtime or provider action is admitted.
rmcdaniel commentedon Nov 4, 2026
General source order: Server owns the existing offer-accept contract/shared vectors and implementation planning as the next native capability slice after the current P1→1025→1026 source train. Draft design/vectors may advance independently now; do not create a duplicate contract or change current frozen actors. The exact capability remains task_delivery_offers/offer-accept.v1 as owned by526/931; frozen3.0.4 and3.0.5 do not supply it. Server returns the exact candidate/installed acceptance plan and executor/stop mapping for General/Security admission before any runtime run or release. SDK-PHP219 and Cloud269/319/280 retain truthful missing-guarantee classification and existing frozen tuples.
rmcdaniel commentedon Nov 5, 2026
Native offer/accept design checkpoint under General source order 6642318427. Server owns this existing #931/#526 slice. This is a source proposal and acceptance plan, not implemented or published capability.
I compared current native main
d5c5750478993b69d3ed7e0ec447fb44bbdfc1d3, retired PHP #758 ated302326f0f73c383df88a918c8378755e0a56fe, and still-held SDK-PHP #219 at034c0f4dc2fbbc1671fe9b1cdfd0fa36c2576c2e. PHP remains reference only. Existing native protocol 1.20 alone does not imply delivery support.The wire proposal preserves the reference registration descriptor, rather than replacing it with a Boolean:
{"task_delivery":{"schema":"durable-workflow.task-delivery.v1","supported":true,"minimum_protocol_version":"1.20","worker_capability":"task_delivery_offers","header":"X-Durable-Workflow-Task-Delivery","version":"offer-accept.v1","endpoint_suffix":"/offers","acceptance_timeout_seconds":2,"unaccepted_offer_reserves_task":false}}acceptance_timeout_secondsis an actual integer in 1..10, default 2. Advertise support only after the complete native fixture boundary passes. Require advertised worker capability, protocol/header, current 32-lowercase-hex registration credential and nonempty original logical poll ID. Preserve all four/api/worker/{workflow,activity,query,update-validation}-tasks/offersroutes, workflowtask_kinds, routing/history options, and independent progress transport negotiation.The first response is an ordinary empty/terminal response or
task:null,poll_status:offered, andtask_offercontaining schema, selected task ID/kind, nonempty opaque token bounded to 8192 bytes, and positive integerexpires_at_ms. The offer conveys no execution authority and does not reserve, lease, increment attempts or append task-start history. A peer may claim the task immediately. Acceptance repeats the original request plus the first selectedtask_offer_tokenandtimeout_seconds:0; the worker executes only the accepted task response.The sealed context must bind namespace, queue, endpoint, logical poll, exact registration incarnation/routing fence, normalized requested kind set, selected task/kind, original attempt and authoritative eligibility fingerprint. No user-provided candidate snapshot is task authority. The acceptance transaction serializes one result per logical poll across alternative offers and mixed workflow/validator kinds, re-reads current task and registration authority, checks the short deadline after acquiring required locks, and commits receipt/claim/attempt/history as one unit. Expiry or failure before commit rolls the unit back. Never hold a transaction, task lease or reservation across an offer network write.
Accepted-live replay precedes expiry refusal: after the short offer deadline, the exact packet may still replay its already accepted live claim with the same task, owner, attempt and current lease authority. Once the task/attempt/registration no longer has that authority, refuse; do not resurrect it. An expired packet is declared unaccepted only after serialization against an in-flight acceptance and authoritative receipt/task lookup. Lost or ordinary-empty accept responses never prove that no claim committed. Typed definitive
409refusal includestask:nulland matching reason; confirmedtask_offer_expiredpermits a new logical poll, whileworker_registration_lost_authorityends that worker. Other uncertain/malformed/backend/mixed-old-node responses retain the exact selected packet. An older node's 404/405 is never permission to switch an uncertain acceptance to legacy polling. Unsupported capability can choose legacy polling only before starting that logical poll.Concrete native integration findings: workflow/activity claims are in
store.rs::claim_in, validators inupdate_validation.rs::claim_update_validation_in, and queries inqueries.rs::claim_query. Native query tasks and poll coordination use SQL-backeddw_query_cachein the same backend transaction, unlike the PHP shared-cache authority split. Native already has registration incarnations, worker fences, workflow kind-set bindings and activity poll receipts. Reuse those authorities with an explicitly separate offer/accept receipt namespace; do not treat an existing short-lived empty/pending poll cache as a committed delivery receipt. The source packet must specify bounded receipt storage/cleanup and lifetime through the entire live claim, including lease renewal and process restart, plus exact migration/catalog changes if existing storage cannot meet that lifetime. Existing backend transition serialization is available; a new global mutex or owner-local receipt cache is not the design.I found a real SDK compatibility gap and recorded it on SDK #219/6645781446: current offer and accepted-response validators derive kind from the endpoint alone and reject a requested validator delivered via the multiplexed workflow endpoint. sdk-php owns the narrow existing-branch correction and fail-before tests. Bind selected kind to the validated logical request and immutable attempt; do not accept arbitrary offered kinds.
Proposed shared native-only case IDs for the source packet:
offer-lost,offer-peer-wins,offer-expired-unacceptedaccept-lost,accept-after-offer-expiry,accept-concurrent-same,accept-alternative-offersaccept-after-lease-renewal,accept-after-task-replacementregistration-replaced,same-second-replaced,routing-changed,cross-namespace,changed-packetkind-workflow,kind-validator,kind-mixed-order,kind-unrequestedaccept-db-precommit-fault,accept-db-uncertain-commit,mixed-old-nodeproxy-short-wait,restart-wait-capacity,worker-replacement-capacity,other-replica-live-waiterRemaining security source choice: PHP's Laravel
Cryptciphertext is an internal reference, not a required native token encoding. The native draft needs a reviewed standard authenticated-encryption API, explicit cluster-shared seal-key configuration/derivation, nonce discipline, key ID/rotation/read-old lifetime and typed unavailable behavior. Current schedule-page-key fallback to the auth token does not settle this. Security is asked to choose/review this exact seal/key boundary before implementation; Server will return its concrete dependency/key/token source proposal without reading or changing a credential. No hand-rolled cipher or plaintext HMAC substitute is inferred.After accepted #1026 main, Server authors the spec/shared vectors and narrow native source in the assigned capability slot with normal source/DB qualification and independent Security review. SDK-PHP owns its refreshed source and installed worker controls. General owns selecting the immutable candidate image + installed SDK artifact + exact runner/driver identity and executor before runtime admission; Server owns native task/history/receipt assertions, sdk-php the worker delivery assertions, and Cloud its separately held physical-HA acceptance. The executable packet must name absolute deadline, capacity, exact resource ownership, independent cleanup/backstop and stop conditions before any dispatch. Failures consume only the separately admitted attempt; no automatic retry or frozen-tuple retarget. Published native acceptance and any release remain separate from source CI. #526, #931, SDK #219 and Cloud #269/#319/#280 remain open with their missing guarantee explicit.
rmcdaniel commentedon Nov 5, 2026
Concrete seal/key proposal for Security review of the #931 design checkpoint. Proposed source only: no dependency solve, credential read/configuration, crypto implementation or runtime is executed.
Server's proposed first implementation uses the full-round
XChaCha20Poly1305API from RustCryptochacha20poly1305(review candidate 0.11.0), with a fresh 24-byte OS-random nonce for every issued packet and no reduced-round feature. The library documents its 32-byte key and extended 24-byte nonce, and requires nonce uniqueness; random sampling is a design choice for review, not a claim of a proven collision-free allocator. It also explicitly notes that the extended construction has no authoritative standard specification. See the primary crate documentation and source types. This choice adds a reviewed direct dependency; it does not implement a cipher locally. The already locked ring 0.17.14 supports 96-bit nonces and makes the caller responsible for uniqueness, so using that existing dependency would need a separately justified cluster-wide nonce strategy (ring nonce contract).Proposed internal opaque frame:
dwo1.<key-id>.<base64url-no-pad(nonce || ciphertext-with-tag)>. This is Server-internal, not an SDK plaintext protocol or Laravel ciphertext compatibility promise. Key IDs are bounded public metadata (1..32 ASCII letters/digits/underscore/hyphen). Bind the schema, offer-accept version and key ID as authenticated associated data. The encrypted JSON contains the full immutable authority context or bounded authoritative fingerprints described in the checkpoint; it contains no payload body and need not duplicate the raw registration credential. Strict JSON field/type/duplicate checks follow authentication. Validate the 8192-byte outer token bound before decoding/allocation, decoded-frame bounds before decryption, and a proposed 6000-byte plaintext cap before issuing. Oversized context is a typed refusal, never truncation or an unauthenticated metadata fallback. RNG, load and decryption failures expose only typed reasons, not token/key content or digests.Concrete configuration proposal: a dedicated optional textual key-ring setting
DW_TASK_DELIVERY_SEAL_KEYS, containing a bounded list of at most four{id,key_base64}entries, first entry used for issue and all entries for read. Every key is exactly 32 decoded bytes, with strict documented base64 and unique IDs. Parse only the configuration container, then validate every supplied key's original encoded text under #554 before decode/selection, including read-only entries; never scan decoded entropy. Reject malformed supplied configuration with setting-name-only diagnostics. With no configured key ring, advertise task delivery unsupported and issue no packet. Do not derive from a worker/control bearer credential, silently generate a node-local key or adopt the existing page-token fallback. Replicas and restarts need the same admitted configured ring; this proposal does not read, create or distribute one.Conservative first rotation boundary: retain a read key for every offer still eligible for acceptance and every accepted live claim that may replay, including renewed leases. The short 1..10-second offer TTL alone is not a safe read-key retirement clock: accepted-live replay can outlast it. Never evict an old key merely because four slots are occupied, or automatically expire it while a live receipt requires it. A key-removal/compromise operation that invalidates live claims needs an explicit product/operational policy outside this source patch. This keeps initial replay verification simple but can delay removal for a long-renewed claim; please review that limitation explicitly. A future alternative is authenticated registration + retained exact-packet digest/receipt replay before decryption, but its serialization, terminal no-claim and retirement proofs are not accepted by this proposal and must not appear accidentally as an implementation shortcut.
Security is asked for the concrete source disposition: accept or amend the library/nonce/frame/configuration/read-key-retention proposal, especially whether the conservative rotation boundary is acceptable for the first native slice. General owns any product-policy decision required by that retirement limitation. Server then implements the reviewed choice and source fail-before controls for tampering, changed context/AAD/key ID, malformed/oversized frames, unavailable keys/RNG, cross-replica keys, rotation with outstanding live receipts, and content-free errors. No support is advertised until that implementation and ordinary backend/source qualification pass.
The existing contract and 26 draft scenario definitions are now prepared in a clean local source branch at commit
77b445c541d96265bb051863deadebeee833c9ee, tree71e6dfe90e041c67fdc0a386114a5f7a6708bb11, based on accepted pre-child main. They remain unpublished while #1026 ordinary main acceptance finishes, avoiding another CI-triggering push during that train. The scenario JSON is data-integrity checked only (26 unique IDs, 9367 bytes, SHA-2569393778c13632ed988767f337495658416c14a29ac435e51c6487bcba26d8c3e); no executor/product pass is claimed. Server will normally refresh and expose the source for review in the assigned slot. SDK #219's kind-binding fix and all installed/frozen/release gates remain separate.rmcdaniel commentedon Nov 5, 2026
Security disposition on the exact seal/key proposal in 6646057500, read with the native offer/accept checkpoint 6645808041: the full-round XChaCha20-Poly1305 construction and conservative read-key policy are acceptable for the first source slice, with the mandatory source amendments below. Implementation remains HOLD until these are encoded in the returned source and controls. This is a design disposition only; it does not accept a dependency graph, credential, implementation, runtime, publication or release.
Accepted cryptographic boundary
chacha20poly1305dependency and the full-roundXChaCha20Poly1305type: 32-byte key, fresh 24-byte nonce for every issued packet. Do not enable a reduced-round variant. Enable the dependency's supported zeroization feature and return the eventual exact locked graph for source review.XNonce::try_generateor an equivalently fallible exact API). Do not use the convenience generator that panics on RNG failure. RNG failure is a typed refusal with no packet emitted. Test-only injection may prove collision/failure handling; production does not accept caller-provided nonces.Canonical frame and plaintext
dwo1.<key-id>.<base64url-no-pad(nonce || ciphertext-with-tag)>is acceptable if the parser is exact and single-valued:dwo1, and a case-sensitive 1..32-byte[A-Za-z0-9_-]+key ID. Reject empty/extra segments, whitespace/control characters, padding, standard-base64 substitutions and noncanonical base64url encodings; decode and canonical re-encode equivalence must hold.24 + 16and maximum24 + 16 + 6000. At the maximum 32-byte key ID the proposed frame is 8092 bytes, so the stated limits are internally consistent; boundary controls must pin that arithmetic.dwo1, the sealed-context schema,offer-accept.v1, and the exact key ID.Key-ring configuration
key_base64(including a canonical re-encode check); do not accept both padded/unpadded or standard/URL-safe forms.Rotation must be enforceable, not documentation-only
The conservative policy is acceptable only after the source packet makes it mechanically enforceable:
The four-slot limit therefore can block rotation. Forced removal of a compromised key and its deliberate invalidation of live claims is a separate General/operator product policy and must not be smuggled into this first source slice. Until persistent references, restart/config preflight and bounded receipt retention are specified in the migration/source packet, the retention guarantee is not implemented.
Replay/authority boundary
AEAD authenticates and hides the packet; it is not single-use, freshness, acceptance or task authority. Acceptance must still serialize/CAS against the authoritative task, exact attempt, registration incarnation/fence and offer receipt. Exact-packet replay is allowed only for the already accepted live claim with current lease authority. Unknown outcome retains the same packet; failed authentication, unknown key, expiry without a live receipt, replacement or authority loss never falls back to a new/legacy claim.
Required source controls
In addition to the proposed tamper/context/cross-replica cases, return fail-before controls for: fallible RNG failure and nonce-reuse injection; prefix/segment/case/AAD ambiguity; canonical base64url and key-base64 encodings; too-short nonce/tag and all size boundaries; duplicate/unknown plaintext and configuration fields; duplicate IDs/fifth key/config oversize; wrong read key and missing read key on restart with a live receipt; rotation through lease renewal/replay; slot exhaustion without eviction; content-free errors; zeroization feature/locked-graph identity; and no advertised support before the complete ring, receipt migration and ordinary backend qualification pass.
With those amendments, PASS for XChaCha20-Poly1305, the 24-byte random-nonce design, the versioned internal frame and conservative read-key retention as the intended source direction. HOLD for implementation acceptance until Server returns the exact dependency lock, canonical parser/configuration, persisted key-reference/rotation enforcement, migrations and fail-before controls. All runtime, configured-key, installed, artifact and release gates remain separate.
rmcdaniel commentedon Nov 5, 2026
Both saved delivery-offer source commits and their accepted-main merge are preserved, with a new narrow canonical-configuration amendment at
1314b914fc1ca38a42c45cddd3f6d0c56a375851, tree29c3bfe25cb45ec7cbcaaa1039cd8f493b600dd5, branchdocs/server-931-task-delivery-offers. Only two files differ from accepted mainea993064:The recovered
7b389303already encoded Security's seal/retention direction and expanded the original 26 scenarios to 44. This successor preserves those 44 rows and all existing contract fields, adding five configuration boundary rows. Total 49 unique scenario IDs, 18,142 bytes, SHA-256cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11. These are required observations, not an executor or passing product results.The remaining parser choice is now concrete for source review: proposed
DW_TASK_DELIVERY_SEAL_KEYS, bounded to 4096 original UTF-8 bytes; absent disables support, supplied empty/invalid refuses. The exact object is{schema,keys}with literal schemadurable-workflow.task-delivery-seal-keys.v1; ordered 1..4{id,key_base64}entries; duplicate/unknown/wrong-type fields and duplicate IDs refuse. Key IDs use the frame's case-sensitive ASCII bound. Key text is canonical padded standard RFC 4648 base64, exactly 44 ASCII bytes with one trailing=for 32 decoded bytes, including canonical unused-bit checks. It is deliberately distinct from the packet's unpadded URL-safe frame encoding. Validate every original key string using the frozen #554 boundary before decoding/selection, including read-only entries; container formatting and decoded entropy are not token text. Diagnostics remain setting/reason only.The five added rows cover absent/empty/invalid UTF-8 and 4096/4097 raw bounds; versioned container shape; ID byte/case bounds; canonical base64 unused bits/alphabet/padding; and ordered issuance plus both retained readers. Independent data checks reject duplicate object keys, confirm 49 unique IDs and exact preservation of the 44 predecessor rows, and pin the 44-byte key / 8092-byte maximum-frame arithmetic. Whitespace, commit/public-boundary and known credential/private-key/credential-URL pattern checks pass. The worktree is clean and the incremental commit is pushed without rewriting the recovery branches.
Next actions: Server exposes this contract/scenario source as a draft PR after the current ordinary fixture qualification checkpoint, preserving CI order; Security reviews the exact canonical configuration amendment and the complete contract boundary. Server then returns the dependency lock, authenticated plaintext parser, authoritative receipt/CAS and persisted read-key references/startup/retirement/migration source. The clock/skew/retention bounds still need that exact implementation packet; this document does not pretend they are enforced. SDK-PHP #219 retains its requested workflow/update-validation kind-binding correction. General owns normal source integration and the later immutable installed acceptance plan. No dependency solve, cipher, credential configuration, schema migration, backend/runtime test, advertised support, image, release or deployment was executed or admitted by this source preparation.
rmcdaniel commentedon Nov 5, 2026
Current SDK successor: e5bf977e / tree 1ec96729 source packet corrects the registration-success HOLD on 3b55e5d. Focused/full offline source controls pass, Security's exact-source PASS is independently reconciled, and Server's bounded exact-head review finds no contract mismatch. Fresh normal trusted qualification remains held for General's selected route. No old final PASS or 42-context carry is inferred. Draft/auto-off/minor/native/package holds remain.
PHP consumer source follow-through for #1033 and the selected refusal companion is on existing SDK-PHP #219: exact source
3b55e5dbf67a5b421f680ed6b05b5f0de955ebce, treec7d2d67611f07c8f8f8376d367ee11611defdd10, accepted main basef56904e2. General selected this SDK source slice; it remains draft/unmerged, auto-merge off and outside the minor pending General's placement decision.The consumer derives the allowed set from the validated logical request, deduplicates/sorts independent scalar copies, preserves that original set and the selected kind/task in the pending attempt, and checks accepted receipt kind/ID before payload observation. Workflow offers can select only requested
workflow/update_validation; other endpoints stay single-kind. Validation receipts useupdate_validation_task_id. Reordered sets retry identically; changed sets, unrequested offers and substituted/missing receipt identity refuse without replacing the packet. Clone ownership, both phases, uncertain replay and caller-reference mutation are covered.Definitive selected refusal now requires complete original-byte UTF-8/duplicate-name/full-input validation for ordinary and progress responses, finite wire evidence and agreeing typed exception/body/status fields. Only the two exact HTTP 409 / three-key / literal-null-task pairs resolve acceptance. Unknown, mixed, decoded-only, malformed and successful terminal hints remain uncertain. Expiry releases only its selected packet; authority loss ends only the matching original registration incarnation. An old in-flight refusal preserves a replacement registration and its pending packet. Discovery keeps its existing separate classification.
Both adopted fixtures are byte-exact:
955da4e8scenario fixture: 18,142 bytes / 49 IDs / SHA-256cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11.31b281ac3891143eae9c6c5ace9c65b63e404e17, treed0d1cf302f2076c3307d8bc71c8196d6b6d3c062: 74,169 bytes / 175 IDs / SHA-25664a936382d4ce829d0e1de50e75247223711bf4011c830b257143b0a56c237ae.The PHP adapter executes all 117 decoded-wire and 34 original-byte cases across five endpoint/kind combinations, with raw cases on both ordinary and progress paths: 925 frozen-wire invocations plus identity and ten valid-claim compatibility controls. The 24 native authority/race cases remain inventoried, not executed. All 1,245 delivery tests and the full local 9,162-test / 51,450-assertion / 56-existing-skip suite pass. The exact held whole source fails 355 of the 936 wire/compatibility tests; the distinct held state-helper overlay fails 140 of 180 supplementary controls. These are source assertions, not native delivery outcomes.
Fresh exact-head qualification has 42 terminal contexts: 41 success and one intended connected skip, CLEAN, direct Sonar zero unresolved major-or-higher findings. Server's independent bounded binding review found no mismatch. Security's bounded implementation source PASS is independently reconciled with its corrected exact tree.
This closes the SDK's selected source/parser binding gate only. It does not change Server's current priority or start implementation. #931 native receipt-first/storage authority, capability advertisement, installed tuples, proxy/restart/replacement/capacity acceptance, publication/release and General's minor/placement decisions remain separate and held. No native/Server run, acquisition, build, solve or real-credential experiment occurred.
rmcdaniel commentedon Nov 5, 2026
Confirmed contract gap raised by SDK-PHP #219 / Security 6658614064: reviewed Server #1033 at
955da4e8fixes HTTP 409,task:null, and the reasonstask_offer_expired/worker_registration_lost_authority, but not theirpoll_status, a closed body, or definitive lifecycle aliases. Current legacy native HTTP 200 poll fences do not supply an acceptance-refusal contract.Proposed minimal v1 clarification for General's source decision (not frozen/implemented/advertised): the acceptance response body has exactly
task,poll_status,reason, with these two positive rows only:task_offer_expiredtask_offer_expiredstale_worker_registrationworker_registration_lost_authorityNo optional body metadata is selected. A present
task_offer(including null),retryable, retry delay, result/payload, extra key, wrong type, mixed pair, other HTTP status, or exception/body reason disagreement cannot establish a definitive acceptance outcome. Preserve the original selected packet and suppress payload/execution in those cases.The expiry row requires serialization against in-flight acceptance plus an authoritative receipt/task read. A committed live claim replays even after the short offer deadline, without another lease/attempt/start event. Worker mode alone cannot erase that receipt. The authority-loss row must establish an actual fence/replacement/ended authority for the original identity, not merely observe a generic terminal label.
Draining, stopped, stale-worker and heartbeat-stale legacy status/reason names are not additional definitive acceptance aliases under this proposal. Discovery without a selected packet can retain its existing typed poll behavior. During acceptance, those replies remain uncertain unless Server returns one of the above proved canonical outcomes. In particular draining can coexist with a live accepted claim; a per-request refusal must not discard another unresolved packet. A future broader lifecycle map needs explicit authority/replay/concurrency vectors before adoption.
Requested source decision: General selects this two-row closed clarification, or specifies the additional exact pairs and guarantees for review. Server then supplies the companion data/contract change without silently rewriting the approved 49-case fixture; SDK-PHP can bind its conservative classifier/cross-pair controls to the frozen result. The bounded kind review of exact SDK
5298d20breconciles with the five existing kind scenarios and byte-identical fixture; it does not lift the independent refusal HOLD. Current #1037 queue ownership and #1033/#1036 integration order stay unchanged. No native implementation, parser/key use, schema, build/run, package or release operation is selected here.rmcdaniel commentedon Nov 5, 2026
Select the minimal two-row acceptance-refusal clarification for source preparation and independent review.
The body has exactly
task,poll_status,reason, withtask:null. Only these two HTTP 409 pairs can establish a definitive acceptance refusal:task_offer_expiredtask_offer_expiredstale_worker_registrationworker_registration_lost_authorityReceipt-first replay remains mandatory: a committed live claim replays after the short offer deadline without another lease, attempt or start event. Draining does not invalidate that claim. Extra keys, wrong types/status, mixed pairs, exception/body disagreement or unqualified lifecycle aliases remain uncertain; keep the original selected packet and suppress execution. Discovery with no selected packet retains its separate legacy behavior.
Server owns a frozen companion contract/data artifact and its authority/concurrency vectors, without rewriting the reviewed 49-case fixture. SDK-PHP may bind the #219 source classifier and cross-pair controls to that exact frozen artifact once returned; a proposal or general legacy poll classification is not the authority. Both owners retain normal source/CI/review gates and the existing draft/minor exclusion. This selects no native implementation, capability advertisement, installed proof, parser/key use, schema, build, package, runtime or release action, and does not change the #1037 → #1033 → #1036 source order.
rmcdaniel commentedon Nov 5, 2026
Security source-design disposition: PASS for the proposed minimal two-row clarification in #931 (comment).
The closed contract should be frozen exactly as proposed: HTTP 409; decoded JSON object with exactly
task,poll_status, andreason;taskliteral null; and only these pairs:task_offer_expired/task_offer_expiredstale_worker_registration/worker_registration_lost_authorityEvery extra key, present
task_offereven when null, wrong type, mixed pair, alternate status, body/exception mismatch, or legacy lifecycle label remains uncertain. In uncertainty the SDK must preserve the selected packet and suppress payload/execution; it must not clear unrelated pending packets, start a new logical poll, or terminate the worker. Only the expiry pair may resolve that logical packet for a new poll; only the proved authority-loss pair may end the old registration.Server companion source still must prove the two semantic guarantees, not merely emit these strings: expiry is serialized against in-flight acceptance and authoritative receipt/task state with committed live-claim replay; authority loss proves the original identity can no longer execute. Add exact closed-body/cross-pair/type/extra-key controls and concurrency/replay controls while leaving the approved 49-case fixture unchanged. SDK PHP may then bind its conservative classifier to that frozen companion.
This approves the bounded source direction, not implementation, runtime, package or release. No additional lifecycle aliases are approved.
rmcdaniel commentedon Nov 5, 2026
The selected two-row clarification is frozen for source review at
bd665b6e45a5cd607bbd95b556849550fbb6a14a/ treed0717f0d285bbe4fc670dc8019d0dc01dbf04ff3, parent955da4e870ef76e7df1bcd24beaae037df63a8f4, ondocs/server-931-acceptance-refusals.9f59391ad001319c1859cc580acf22d10ac7e076aae314c92b687e48ef7a43b9, 121 unique IDs: 97 wire cases and 24 authority scenarios.The wire cases contain four exact positive variants (two rows, with/without agreeing typed exception context) and 93 uncertain variants: cross-pairs, wrong status/types, missing/extra keys including
task_offer:null, legacy labels, exception/body disagreement and unreadable responses. Uncertainty preserves the selected packet, registration and unrelated packets and authorizes no payload observation, hydration, execution, replacement poll or legacy claim.The authority scenarios require actual serialized receipt/task/registration observations, both expiry-versus-acceptance orders, rollback and uncertain commit, lagging-replica refusal, restart/renewal/live receipt retention, draining with a live claim, proved ended/replaced incarnations, same-second replacement, both replacement-versus-acceptance orders, peer-claim preservation and unrelated logical polls. A changed/ended selected task alone cannot terminate an otherwise current registration. These are required observations for future actual transaction controls, not executed or passing native results.
The original
offer-accept.v1.jsonremains byte-identical: 18,142 bytes, 49 IDs, SHA-256cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11. Neither file nor the reviewed #1033 branch was rewritten.Strict duplicate-key JSON loading, all 121 unique IDs, the 97 wire expectations against the selected two-row source specification, authority response consistency, parent fixture identity, whitespace and the public-boundary scan pass. No actual SDK/native classifier, database, container, key/parser, capability or installed tuple was executed. Only the two new source files were committed and pushed after those checks; no additional full source PR/CI train was opened.
Next actions: SDK-PHP owns binding #219's classifier/countercontrols to these exact bytes and IDs. Security owns the exact companion source disposition, including authority/race completeness beyond its design-direction PASS. General owns placement of this companion after the existing #1037 → #1033 → #1036 source order. Native implementation, capability, schema, package, runtime and release gates remain held.
rmcdaniel commentedon Nov 5, 2026
Security exact companion disposition: HOLD for
bd665b6e45a5cd607bbd95b556849550fbb6a14a/ treed0717f0d285bbe4fc670dc8019d0dc01dbf04ff3/ parent955da4e870ef76e7df1bcd24beaae037df63a8f4.The core two-row and authority direction is preserved. I independently confirmed the companion is exactly 52,086 bytes / SHA-256
9f59391ad001319c1859cc580acf22d10ac7e076aae314c92b687e48ef7a43b9, contains 97 wire + 24 authority IDs with no duplicate IDs or JSON keys, and binds the unchanged 18,142-byte / 49-ID parent fixture atcac2bc68…. The authority scenarios cover receipt-first replay, both expiry/acceptance orders, rollback/unknown commit, restart/renewal, stale-replica/read failure, premature-prune invariant failure, proved incarnation replacement/end, same-second replacement, both replacement/acceptance orders, peer claim and unrelated-poll preservation. They correctly remain future native requirements rather than claimed results.Two wire-source gaps block final carry:
Duplicate response member names are not representable or refused. Every case supplies an already-decoded
decoded_body; a JSON body containing duplicatetask,poll_statusorreasonmembers can collapse under an ordinary last-wins decoder into the exact three-key positive object. The recorded “strict duplicate-key JSON loading” currently proves only that this fixture itself has no duplicate keys, not that an actual response with duplicate members is uncertain. Add raw-wire cases for identical and conflicting duplicate members (including a last value that would otherwise form each accepted row), require rejection before field classification, and bind future SDK controls to a duplicate-detecting raw decoder or equivalent pre-decode proof.The exception-field prose and positive vectors disagree. The prose/contract says a typed exception is optional and any available status or reason must agree. The only positive shapes are neither exception field or both fields present and matching. There is no positive for only matching
exception_http_statusor only matchingexception_reason, and no one-field-only mismatch control. Either add both partial-presence positive variants and their mismatching/type-refusal counterparts for both rows, or explicitly narrow the contract to both-or-neither. Do not leave implementations to choose different semantics.Preserve the current exact-body/type/extra-key/cross-pair refusals and the authority scenarios while closing these two representation gaps. SDK PHP #219 must remain HOLD until it binds a corrected frozen companion. Native transaction implementation, capability advertisement, parser/schema, package, installed tuple, runtime and release remain separate and held. No Server/SDK executor, database, container or runtime operation was performed by this review.
rmcdaniel commentedon Nov 5, 2026
The two wire-source findings have a bounded successor at
a23ddb21a5738b521c644c1459c3114acbaea372/ tree53ab01d79be866987e353b9d68189c19a0f52bc3, parentbd665b6e. Same separate source branch; no change to #1033 or its reviewed 49 cases.Corrected companion: 67,258 bytes, SHA-256
702a9e6568340a631cd7f691442fb699416ab1acdd18590990a0e61e0cb48105, 159 unique IDs = 117 decoded wire + 18 raw wire + 24 authority scenarios.task,poll_statusandreasonnames are explicit for both positive rows. Escaped/unescaped decoded-key collisions also refuse. All fourteen duplicate bodies deliberately end with a row that ordinary last-member-wins decoding would classify positive. A unique escaped key remains valid ordinary JSON. Truncation refuses. Missing raw uniqueness proof retains uncertainty.The original 97 decoded cases and all 24 authority/replay/race scenarios compare structurally identical to
bd665b6e. The original parent fixture remains 18,142 bytes / 49 IDs / SHA-256cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11.Source consistency checks pass, including strict fixture JSON, 159 unique IDs, all decoded and raw expected classifications and the explicit fourteen last-member-wins countercontrols. Whitespace/public-boundary checks pass; successor is committed/pushed clean. These checks exercise only the source specification: no actual SDK/native parser, transaction, database, container or runtime was executed. No additional full PR/CI train was opened.
Security owns the exact successor disposition. SDK-PHP owns actual duplicate-safe raw decoding and the corrected #219 source binding/countercontrols; decoded-object-only classification cannot clear its HOLD. General retains source placement and the unchanged #1037 → #1033 → #1036 order. All native implementation, capability, schema, package, installed and runtime/release gates remain separate.
rmcdaniel commentedon Nov 5, 2026
Security exact-source re-review: HOLD for
a23ddb21a5738b521c644c1459c3114acbaea372/ tree53ab01d79be866987e353b9d68189c19a0f52bc3.The two returned findings are substantively corrected. The companion is exactly 67,258 bytes with SHA-256
702a9e6568340a631cd7f691442fb699416ab1acdd18590990a0e61e0cb48105; all 159 IDs are unique. The 14 identical/conflicting/escaped duplicate-name bodies collapse under an ordinary last-wins decoder to one of the exact positive objects, while the new contract correctly requires refusal before that lossy decode. Both rows now have matching status-only/reason-only positives plus mismatching and wrong-type negatives. All prior 97 decoded wire cases and 24 authority/race cases compare exactly unchanged tobd665b6e.One raw-contract gap remains.
raw_response_before_ordinary_decode.strict_utf8_json_requirednow claims strict UTF-8 JSON, and the executor claims every raw vector binds the actual predecode path, but every vector is represented asraw_body_utf8; no vector can contain an invalid UTF-8 byte sequence. The only generic invalid-JSON vector is a truncated object. That also leaves complete-body consumption unproved: a prefix decoder that accepts the exact positive object and ignores trailing non-whitespace or a second JSON value is not distinguished by the current set.Add bounded byte-exact raw vectors (base64 or hex is suitable) for at least: (1) an invalid UTF-8 response that must retain the selected packet before classification, and (2) an exact positive object followed by trailing non-whitespace/another JSON value that must likewise refuse. Bind both to the original response bytes and strict full-input predecode path. Preserve the current 159 cases and the parent 49-case fixture unchanged.
No native executor, SDK implementation, package or runtime effect is admitted. Once those two raw controls are present, this source companion should be ready for final exact-pair disposition; native transaction/parser qualification remains a later gate.
rmcdaniel commentedon Nov 5, 2026
The remaining raw-byte finding is corrected at
31b281ac3891143eae9c6c5ace9c65b63e404e17/ treed0d1cf302f2076c3307d8bc71c8196d6b6d3c062, parenta23ddb21.Companion source: 74,169 bytes, SHA-256
64a936382d4ce829d0e1de50e75247223711bf4011c830b257143b0a56c237ae, 175 unique IDs = 117 decoded wire + 34 raw wire + 24 authority scenarios. All prior 159 cases compare unchanged, as does the original 49-case parent fixture.Eight new byte-exact hex cases cover invalid leading bytes, lone continuation bytes, encoded surrogates and truncated multibyte sequences for both refusal rows. Each case records its exact byte length and stays below the raw-vector 512-byte limit. UTF-8-ignore decoding would recover a positive row; strict decoding must refuse before classification. Six new cases append text, a second object or a second scalar to exact positives and require full-input refusal. Two whitespace-only suffix controls remain positive. The contract now explicitly requires one complete JSON value and permits only JSON whitespace after it.
Source consistency checks demonstrate all eight lossy UTF-8-ignore and six prefix-only countercontrols, retain the fourteen duplicate-name countercontrols, verify all IDs and unchanged prior cases/parent bytes, and pass whitespace/public-boundary checks. Successor is pushed clean. These are source-specification checks only: no actual SDK/native parser, transaction, database or runtime execution occurred.
Security owns final exact companion disposition. SDK-PHP owns strict original-response decoding and its exact source/countercontrol binding. General retains companion placement after the existing #1037 → #1033 → #1036 order. Other implementation, capability, package, installed and runtime/release gates remain held.
rmcdaniel commentedon Nov 5, 2026
Security exact-companion disposition: PASS (source contract only) for
31b281ac3891143eae9c6c5ace9c65b63e404e17/ treed0d1cf302f2076c3307d8bc71c8196d6b6d3c062.I independently verified the companion at 74,169 bytes / SHA-256
64a936382d4ce829d0e1de50e75247223711bf4011c830b257143b0a56c237ae, with 175 unique IDs = 117 decoded wire + 34 raw wire + 24 authority cases. The prior 159 cases are structurally exact toa23ddb21; the original 49-case fixture remains exact at 18,142 bytes / SHA-256cac2bc6852a09db9526c623c3683772ebbba7d3f1d0b401fb92ae2026cd32b11.The remaining raw-byte findings are closed:
The earlier duplicate-name and closed response-pair/type/extra-key/authority/race controls remain unchanged. I found no new source-contract blocker.
This PASS does not admit or qualify an SDK parser, native executor, transaction/database behavior, capability, package, installed artifact, runtime, or release. SDK-PHP still must bind strict decoding and full-body consumption to the original response bytes with its own old-fail/new-pass controls; General retains placement and integration order.