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
Two of these are internal inconsistencies rather than mere omissions, which makes them cheap to fix
and embarrassing to leave: #5 (the initial search gets the total right and the scroll page does
not) and #9 (the scroll path emits the real index name and the search path emits "unknown"). In
both cases the correct code is in the same file as the incorrect code.
#3 and #4 are the two that invert a meaning. Deleting a document that was never there reports
success and a version bump, so a consumer's "delete then assert gone" test cannot distinguish a
working delete from a no-op. Getting an absent document returns an error envelope where OpenSearch
returns a body with found: false — a distinction the OpenSearch clients rely on, since found: false is a normal outcome and an error is not.
#7 and #8 are the two that discard stored input.createIndex stores settings, and GetIndex
answers a constant instead of reading them; PUT _mapping assigns its index to _ and acknowledges.
A consumer configuring shards, replicas or an explicit mapping — the three things one configures on an
index — gets an acknowledgement and no effect.
Why this matters
The OpenSearch data plane is the one surface in this batch that a consumer uses directly rather than
through an IaC tool, because application code talks to it on every request. So these are not
provisioning-time divergences a consumer meets once; they are the shapes their application reads in
its hot path. A client library that switches on found, retries on errors: true, or paginates a
scroll by comparing hits.total to the number seen so far behaves differently against substrate than
against OpenSearch — and #5 in particular makes a scroll loop that compares against hits.total
terminate after the first page or never.
They are one issue because they share one verification technique — assert the raw JSON of each
response against the published shape — and because fixing them individually would mean ten passes over
the same three functions.
Acceptance criteria
A write to an existing document answers 200, a new one 201, with _version incrementing
and _primary_term present.
Bulk supports update, and errors is true when any item failed. A test asserts a mixed bulk
request — one success, one failure — reports errors: true with the per-item status.
Deleting an absent document answers 404 with result: "not_found".
Getting an absent document answers 404 with found: false in a normal body, not an error
envelope.
A scroll page reports the query's total, matching the initial search's already-correct behaviour.
HEAD on an index answers no body.
GetIndex reports the settings createIndex stored, and PUT _mapping stores a mapping that GET _mapping returns.
Every hit reports its real _index, matching the scroll path's already-correct behaviour.
The error envelope carries root_cause.
Every response is asserted as raw JSON against the published shape, following iam_shape_members_test.go:115. This is the load-bearing criterion: substrate's existing
OpenSearch tests decode into its own structs, which is why ten divergences survived.
docs/services.md's OpenSearch section states, per operation, what the response carries.
Provenance
Every published shape above is from the OpenSearch REST API documentation: the index-document response
members including _primary_term and the 200-versus-201 rule; the Bulk API's four actions and its errors member; the Delete API's result: "not_found" at 404; the Get API's found: false body at
404; the Scroll API's hits.total; the Index Settings and Mapping APIs; and the error-response
envelope with root_cause. Where a shape is published by OpenSearch (the open-source project's REST
reference) rather than by an AWS API Reference page, that is the authority AWS's own OpenSearch Service
documentation points to for the data plane, and the citation is recorded as such.
In-tree, all in emulator/opensearch_plugin.go: :86, :128-131, :183-190, :195-197, :233-240, :246, :259-274, :298-346, :417, :494, :513, :832, :1048-1062. Line citations are from
the tree at the commit this issue was filed against.
What
Eight response-fidelity defects in OpenSearch's data plane. Each is small; together they mean no
OpenSearch response can be trusted field-by-field.
_version: 1,_seq_no: 0and no_primary_term:233-240_versionincrements;_primary_termis a published member of every write responseindex,create,deleteand hard-codes"errors": false:298-346updateis a published action;errorsis true when any item failedresult: "deleted",_version: 2:259-274result: "not_found":246{"_index":…,"_id":…,"found": false}— a body, not an errorhits.total:513:417HEADon an index answers a JSON body:86HEADcarries noneGetIndexhard-codes 1 shard / 0 replicas:183-190createIndexalready stores at:128-131PUT _mappingis_ = index+{"acknowledged": true}:195-197GET _mapping_index: "unknown":832:494root_cause:1048-1062{"error": {"root_cause": [...], "type":…, "reason":…}, "status":…}Two of these are internal inconsistencies rather than mere omissions, which makes them cheap to fix
and embarrassing to leave: #5 (the initial search gets the total right and the scroll page does
not) and #9 (the scroll path emits the real index name and the search path emits
"unknown"). Inboth cases the correct code is in the same file as the incorrect code.
#3 and #4 are the two that invert a meaning. Deleting a document that was never there reports
success and a version bump, so a consumer's "delete then assert gone" test cannot distinguish a
working delete from a no-op. Getting an absent document returns an error envelope where OpenSearch
returns a body with
found: false— a distinction the OpenSearch clients rely on, sincefound: falseis a normal outcome and an error is not.#7 and #8 are the two that discard stored input.
createIndexstoressettings, andGetIndexanswers a constant instead of reading them;
PUT _mappingassigns its index to_and acknowledges.A consumer configuring shards, replicas or an explicit mapping — the three things one configures on an
index — gets an acknowledgement and no effect.
Why this matters
The OpenSearch data plane is the one surface in this batch that a consumer uses directly rather than
through an IaC tool, because application code talks to it on every request. So these are not
provisioning-time divergences a consumer meets once; they are the shapes their application reads in
its hot path. A client library that switches on
found, retries onerrors: true, or paginates ascroll by comparing
hits.totalto the number seen so far behaves differently against substrate thanagainst OpenSearch — and #5 in particular makes a scroll loop that compares against
hits.totalterminate after the first page or never.
They are one issue because they share one verification technique — assert the raw JSON of each
response against the published shape — and because fixing them individually would mean ten passes over
the same three functions.
Acceptance criteria
_versionincrementingand
_primary_termpresent.update, anderrorsis true when any item failed. A test asserts a mixed bulkrequest — one success, one failure — reports
errors: truewith the per-item status.result: "not_found".found: falsein a normal body, not an errorenvelope.
HEADon an index answers no body.GetIndexreports the settingscreateIndexstored, andPUT _mappingstores a mapping thatGET _mappingreturns._index, matching the scroll path's already-correct behaviour.root_cause.iam_shape_members_test.go:115. This is the load-bearing criterion: substrate's existingOpenSearch tests decode into its own structs, which is why ten divergences survived.
docs/services.md's OpenSearch section states, per operation, what the response carries.Provenance
Every published shape above is from the OpenSearch REST API documentation: the index-document response
members including
_primary_termand the 200-versus-201 rule; the Bulk API's four actions and itserrorsmember; the Delete API'sresult: "not_found"at 404; the Get API'sfound: falsebody at404; the Scroll API's
hits.total; the Index Settings and Mapping APIs; and the error-responseenvelope with
root_cause. Where a shape is published by OpenSearch (the open-source project's RESTreference) rather than by an AWS API Reference page, that is the authority AWS's own OpenSearch Service
documentation points to for the data plane, and the citation is recorded as such.
In-tree, all in
emulator/opensearch_plugin.go::86,:128-131,:183-190,:195-197,:233-240,:246,:259-274,:298-346,:417,:494,:513,:832,:1048-1062. Line citations are fromthe tree at the commit this issue was filed against.