> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Adapter Investigation Playbooks

> Plan bounded adapter investigations from an origin request to independent target evidence.

These playbooks define the evidence to collect for an adapter investigation. They are acceptance procedures, not captured product-test transcripts. Do not convert an expected result below into an observed result until the request, explanation report and target check have all been recorded for the same test identity.

An adapter investigation is strongest when it answers one narrow question with three independent views:

1. the origin-shaped request and response;
2. the explanation report; and
3. the target resource or service state.

No one view replaces the others. A receipt locates a report but does not prove that an operation completed. A report can describe an attempted target call without proving that the provider committed it. A target object proves that an object exists, but not which request created it.

The examples below use synthetic names and data. Use a test deployment unless the customer has approved a live investigation. Preserve the first result before retrying a mutation.

## Playbook 1: S3 `PutObject` to Cloud Storage

**Question:** Does an S3 `PutObject` request map to the expected Cloud Storage object, and what can the explanation establish about that mapping?

Read the [S3 service profile](/cloud-adapter/service-catalog/aws/databases-storage/s3#on-google-cloud) first. It is the source for operation coverage and behavioral differences. This example covers a small direct upload. It does not establish multipart, resumable-upload, versioning or large-payload behavior.

### Inspect the selected profile

Profile inspection does not launch an adapter or contact Google Cloud:

```bash theme={null}
tensor9 explain \
  -origin aws::1.0.0::s3 \
  -target google::1.0.0::gcs \
  -operation PutObject \
  -fmt Human
```

Confirm that the profile names `PutObject`, the S3 origin and the Cloud Storage target. The profile describes supported behavior. It is not evidence from a particular request.

### Separate preview from execution

Use two keys so the evidence cannot be confused:

| Request   | Key                     | Mode                | Expected target effect          |
| --------- | ----------------------- | ------------------- | ------------------------------- |
| Preview   | `explain/planned.txt`   | `Explain`           | No object is written            |
| Execution | `explain/performed.txt` | `ExecuteAndExplain` | The adapter attempts the upload |

For the preview, send an explicit control rather than relying on the deployment default:

```json theme={null}
{"version":1,"mode":"Explain","fmt":"Json"}
```

For the executing request:

```json theme={null}
{"version":1,"mode":"ExecuteAndExplain","fmt":"Json"}
```

<Warning>
  The shorthand `x-t9-explain: true` means `ExecuteAndExplain`. A `PutObject` carrying that value can write the object.
</Warning>

The control must be added before SigV4 signing. See [Explaining Requests from Your SDK](/cloud-adapter/debugging/explain-sdk) for complete client construction and both endpoint configuration methods.

### Collect the evidence

For each request, retain:

* HTTP status, S3 request identifiers and ETag, when returned;
* `x-t9-explain-id`, `x-t9-explain-mode` and revision fields;
* the retrieved report before acknowledgment;
* the Cloud Storage lookup for the exact bucket and key; and
* a digest or byte comparison for the synthetic payload.

The acceptance criteria are deliberately asymmetric:

| Evidence                  | Preview key               | Executed key                                           |
| ------------------------- | ------------------------- | ------------------------------------------------------ |
| Explanation               | Planned S3-to-GCS mapping | Mapping plus attempted and observed work               |
| Native S3-shaped response | Diagnostic response       | Ordinary `PutObject` response, unless execution failed |
| Cloud Storage lookup      | Object absent             | Object present only after a successful upload          |
| Payload check             | Not applicable            | Bytes equal the original payload                       |

An ETag alone does not prove that the report is complete or that every payload byte was persisted. Verify the object through Cloud Storage. Conversely, a missing final response does not prove that no object was written. Check the target key before retrying.

### Read the causal sequence

A useful report separates these steps:

1. identify the S3 operation, bucket and key;
2. resolve the bucket to its Cloud Storage target;
3. map S3 metadata and content properties;
4. authorize and attempt the target upload;
5. observe the target result available to the adapter; and
6. return the S3-shaped response.

`planned` is not `attempted`, and `attempted` is not `committed`. If the report ends after the upload attempt, treat the outcome as uncertain until the native lookup resolves it.

### Decide the next action

* **Preview produced an object:** stop. The request did not behave as a hypothetical explanation.
* **Execution returned success but the object is absent:** preserve the report and target lookup. Check the exact bucket mapping and target request identifier.
* **Object exists but the client timed out:** compare content before deciding whether a retry is safe.
* **Metadata differs:** compare only the fields the S3 profile says are mapped. Do not infer unsupported parity from the object body.

Delete only `explain/performed.txt` after recording an observed cleanup result. Stopping an adapter process does not undo the upload.

## Playbook 2: DynamoDB `CreateTable` to provisioned Cosmos DB

**Question:** Which provisioned Cosmos DB mapping is selected for a DynamoDB table request, and which facts are still needed before declaring the table ready?

Start with the [provisioned Cosmos DB mapping](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#azure-cosmos-db-provisioned). DynamoDB has several Azure mappings, so the target identifier is part of the evidence:

```bash theme={null}
tensor9 explain \
  -origin aws::1.0.0::dynamodb::table \
  -target azure::1.0.0::cosmosdb::provisioned \
  -fmt Json
```

The `::table` facet selects the directed profile. It is not the runtime service name used by an AWS SDK.

### Use a complete, bounded request

The application-facing input remains an ordinary DynamoDB request. For example, a Java application can construct the bounded test table like this:

```java theme={null}
CreateTableRequest request = CreateTableRequest.builder()
    .tableName("orders-explain-test")
    .attributeDefinitions(AttributeDefinition.builder()
        .attributeName("pk")
        .attributeType(ScalarAttributeType.S)
        .build())
    .keySchema(KeySchemaElement.builder()
        .attributeName("pk")
        .keyType(KeyType.HASH)
        .build())
    .billingMode(BillingMode.PAY_PER_REQUEST)
    .build();
```

Do not send the request merely to obtain diagnostic evidence. In an approved test deployment, add the signed explicit version-1 `x-t9-explain` control with mode `Explain` through an explanation-aware request path. The hypothetical report should let you inspect validation, selected mapping, required dependencies and intended work without treating a provider allocation as complete. The [SDK request guide](/cloud-adapter/debugging/explain-sdk) explains the signing boundary and why an ordinary generated client cannot decode an `Explain` document as a normal `CreateTableResponse`.

### Read the sequence, not only the last line

```mermaid theme={null}
sequenceDiagram
    participant SDK as DynamoDB client
    participant Adapter as Service adapter
    participant Report as Explanation report
    participant Cosmos as Cosmos DB

    SDK->>Adapter: Signed CreateTable + explicit mode
    Adapter->>Report: Record validation, profile and dependency evidence
    alt Explain
        Adapter-->>SDK: Diagnostic document, no target action
    else ExecuteAndExplain
        Adapter->>Cosmos: Perform supported table work for configured mapping
        Cosmos-->>Adapter: Native result or current state
        Adapter->>Report: Record attempted and observed evidence
        Adapter-->>SDK: DynamoDB-shaped response + report receipt
    end
    SDK->>Report: Read later revisions without replaying CreateTable
```

Text equivalent:

```text theme={null}
CreateTable request
  -> validate DynamoDB schema and supported options
  -> select the provisioned Cosmos DB profile
  -> resolve the configured account, database and container mapping
  -> describe required registration and target work
  -> observe provider-visible state when execution is authorized
  -> return DynamoDB-shaped table state
```

For an executing investigation, distinguish each state:

| State                   | What it establishes                     | What it does not establish                     |
| ----------------------- | --------------------------------------- | ---------------------------------------------- |
| Request accepted        | The adapter accepted the origin request | Cosmos DB is ready                             |
| Mapping selected        | The provisioned profile was chosen      | Capacity was allocated or changed              |
| Target call attempted   | The adapter contacted the target API    | The provider committed the change              |
| Provider state observed | A native resource was visible           | DynamoDB behavior is identical                 |
| DynamoDB state `ACTIVE` | The adapter considers the table ready   | Every optional DynamoDB operation is supported |

Provisioned capacity is a target configuration decision. Record the configured capacity separately and verify the effective value through the native Azure resource view. Do not infer request units from `PAY_PER_REQUEST`, a successful profile lookup or an accepted `CreateTable` response. Only claim that a request changed capacity when the selected profile documents that input and the explanation plus native target evidence show the change.

### Compare evidence before retrying

If the report is partial while Cosmos DB is still provisioning, poll the explanation receipt and the normal origin status operation. Do not resend `CreateTable` merely to obtain a later report revision. A later revision may add provider observations without running the operation again.

If the origin response and target state disagree, preserve:

* the exact DynamoDB table name and selected target mapping;
* explanation ID, mode and revision;
* provider operation or request identifiers;
* the last origin-facing table state;
* the native Cosmos DB account, database and container state; and
* the configured capacity and the effective capacity shown by the native target.

Cleanup is complete only when the authorized delete has an observed outcome. A hypothetical delete explanation is useful for reviewing dependencies, but it does not remove the table or its target state.

## Playbook 3: a VPC deletion refused by a dependency

**Question:** Why was `DeleteVpc` refused, and can the operator inspect the blocker without deleting anything?

Read the [VPC service profile](/cloud-adapter/service-catalog/aws/networking-traffic/vpc) for the selected target. Use `Explain` against the existing resource first.

An explanation can show that the caller was authenticated and that the requested VPC still has a dependent resource. Those are separate facts:

```text theme={null}
event-decision: DeleteVpc cannot continue
fact-authorization: the evaluated request was allowed
fact-constraint: an attached dependency blocks deletion
fact-target-mapping: the AWS VPC maps to the named target network
```

The authorization fact is not a denial. The operation is refused because the dependency constraint is unsatisfied. The next safe action is to inspect the named dependency and determine who owns it. Do not convert the hypothetical teardown into an executing request until its effect and ownership are approved.

### Know when a report may not exist

Report availability is service and failure-path specific. The inspected VPC path can explain an authenticated dependency refusal. An S3 request rejected before report creation may have no explanation receipt. In both cases, absence of a report is not proof that a mutation had no effect.

## Package evidence for a BYOC incident

For a customer deployment, add the deployment context described in [Debugging Service Adapters](/byoc/service-adapters/debugging/overview): application, customer, release, target mapping, adapter version, timestamp, request identifiers and native target observations.

Keep observed facts separate from conclusions. A concise handoff might say:

```text theme={null}
Observed
- orders-api in example-customer/example-release sent PutObject once.
- The adapter returned report ID exp-… revision 2.
- Cloud Storage contains the expected test key and matching bytes.

Derived
- The configured S3 bucket resolved to the recorded GCS bucket.

Unknown
- Whether an earlier timed-out attempt also reached the target.

Next test
- In the approved test deployment, repeat with a unique key and explicit Explain mode.
```

Remove credentials, signed URLs, customer payloads and unrestricted logs before sharing. An Agent-format report is still customer evidence and does not grant access to the deployment that produced it.
