> ## 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.

# Artifacts

Tensor9 BYOC enables the secure and reliable deployment of vendor application
artifacts (such as container images and models) into customer-connected
appliances using Infrastructure as Code (IaC).

Artifacts are the essential files needed for your application to run. Tensor9 BYOC
focuses on two primary artifact kinds:

1. Files in an object store (e.g., S3 objects)

   ```hcl {3-4} theme={null}
   resource "aws_lambda_function" "example_lambda" {
      function_name = "example-function"
      s3_bucket     = "example-bucket"
      s3_key        = "example-key"
      handler       = "index.handler"
      runtime       = "nodejs24.x"
      role          = aws_iam_role.example_lambda_role.arn
   }
   ```

2. Container images (stored in ECR)

   ```hcl {18} theme={null}
   resource "kubernetes_manifest" "example_deployment" {
      manifest = {
         "apiVersion" = "apps/v1"
         "kind"       = "Deployment"
         "metadata" = {
            "name"      = "example-deployment"
         }
         "spec" = {
            "replicas" = 2
            "selector" = {
               "matchLabels" = {
                  "app" = "example-app"
               }
            }
            "spec" = {
               "containers" = [{
                  "name"  = "example-container"
                  "image" = "123456789012.dkr.ecr.us-west-2.amazonaws.com/example-image:example-tag"
                  "ports" = [{
                     "containerPort" = 80
                  }]
               }]
            }
         }
      }
   }
   ```

## Artifact deployment strategies

Tensor9 BYOC supports two primary strategies for moving artifacts from the vendor's
source environment to the customer's appliance environment: Copy during
deployment or direct reference.

### 1. Copy during deployment model: Default and recommended

In the Copy model, the Vendor Controller copies the artifact from the vendor's
source location to a dedicated artifact repository within the customer's
appliance account during the deployment process. In this model, only the Vendor
Controller requires read access to the artifacts and the vendor does not have to
grant read permissions for each artifact to every appliance.

| Scenario              | Description                                                                                                                                                        | Tensor9 BYOC Action                                                                                                                                                        |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Deploy-Time Artifacts | Artifacts needed for the infrastructure resource definition (e.g., a Container Image referenced in an ECS Task Definition or a Lambda function zip archive in S3). | Tensor9 BYOC automatically detects the artifact in your Terraform, copies it to the appliance account, and updates your compiled code to point to the new, local location. |
| Run-Time Artifacts    | Artifacts referenced at runtime (e.g., an LLM Model in S3) that need to be available in the appliance.                                                             | You declare the artifact with an S3 data source rather than relying on Tensor9 BYOC to find it inside a resource, and Tensor9 BYOC copies it as part of the apply step.    |

#### Vendor workflow (container image copy):

1. Your CI/CD builds the container image and publishes it to your origin ECR repository.
2. Your Terraform references the image using its full path/tag in your compute resource definition (e.g., `resource.aws_ecs_task_definition.container_definitions[*].image`).
3. When you run the Tensor9 BYOC build and apply steps, the compiler:
   * Identifies the artifact reference.
   * Creates a process to copy the artifact from your ECR to the appliance's ECR.
   * Rewrites your compiled infrastructure resource to reference the new, appliance-local ECR path.

### 2. Direct reference model: Override

In the Direct Reference model the artifact is not copied. The appliance is
configured to reach out and pull the artifact directly from the vendor's source
location.

This model is generally reserved for special cases, such as:

* Publicly accessible artifacts from sources trusted by both the vendor and the customer.
* Extremely large artifacts where minimizing data transfer/copy costs through the Vendor Controller account is critical.
* Artifacts that the vendor only wants to access dynamically at runtime.

| Action           | Vendor Requirement                                                                                                                                                                                              |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Override Default | You must provide an annotation in your IaC to explicitly tell the Tensor9 BYOC compiler to skip copying a specific artifact reference.                                                                          |
| Permissions      | You are responsible for managing cross-account permissions (e.g., setting up appropriate IAM roles/policies) to ensure the customer's appliance can read the artifact directly from your vendor source account. |

## Copy during deployment details

### How Tensor9 BYOC finds your artifacts

Tensor9 BYOC finds artifacts two ways, and the difference decides whether you have to write anything at all.

**By consumer.** This is the default, and it asks nothing of you. The compiler walks resource shapes it already understands, and a field's position in one of those shapes is enough to say what the field holds: an ECS task definition's `image`, a Kubernetes pod spec's `containers[].image`, a Lambda function's `s3_bucket` / `s3_key` / `s3_object_version`. Both examples at the top of this page are found this way.

**By declaration.** Where position cannot tell Tensor9 BYOC anything, you name the artifact with a data source. The case that forces this is an image reference the compiler has no way to rewrite, such as one inside a Helm chart's `values`, which is a YAML string rendered at plan time and carries no reference to rewrite. Name the image with the Terraform block that already exists for it:

```hcl theme={null}
data "aws_ecr_image" "worker" {
  registry_id     = var.vendor_account_id
  region          = var.vendor_region
  repository_name = "worker"
  image_tag       = var.worker_tag
}
```

Tensor9 BYOC replaces that block with the appliance's copy, and every reader of `data.aws_ecr_image.worker.image_uri` reads the copy instead. Your arguments are moved into the copy as expressions rather than resolved during compilation, so a tag supplied at deploy time copies the image you actually deploy rather than the variable's default.

Two data sources in the same module that name the same image with the same expressions share a single copy, so spelling one image twice costs nothing.

#### What a declared image requires

| Requirement                                                    | Why                                                                                                                                                                                                                                                                                                                                               |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `registry_id`, `region`, and `repository_name` all written out | Terraform treats the first two as optional and falls back to your provider's account and region. The copy is fetched from outside that account and region, so the fallback would name the wrong registry, and there is no second place to read the right coordinates from.                                                                        |
| `image_tag` or `image_digest`                                  | The copy is addressed by a single image reference, which needs a tag or a digest.                                                                                                                                                                                                                                                                 |
| No `most_recent`                                               | `most_recent` is a query over the repository rather than a name for one image.                                                                                                                                                                                                                                                                    |
| Every reference read inside the appliance                      | The copy is made during the deployment, so its attributes are not available to a `count` or `for_each` expression (Terraform resolves those while planning), nor to an output, a module call, or a resource that stays in your own account.                                                                                                       |
| Only the attributes the copy records                           | `image_uri`, `image_digest`, `image_tag`, and `repository_name` are rewritten onto the copy everywhere, and `registry_id` and `region` wherever the appliance copies into ECR. `image_tags`, `image_pushed_at`, `image_size_in_bytes`, and `id` are not recorded at all, so reading one is a compile error rather than a reference left dangling. |

#### Data sources also carry what only a plan-time read can produce

A data source gives Tensor9 BYOC something a bucket and key written out as literals cannot: attributes that exist only because your own provider read the artifact while planning. [Git delivery](/byoc/fundamentals/artifact-git-delivery) rests on exactly that. Its source must be a `data "aws_s3_object"` block, because the object's `version_id` and `etag` come from an S3 `HeadObject` your provider performs at plan time, and those two values are what tell Tensor9 BYOC you have republished the artifact.

### Artifact naming requirements

To ensure immutability and prevent race conditions during deployments, Tensor9 BYOC requires all vendor artifacts to be uniquely named and immutable.

| Artifact Type | Naming Requirement                             | Why?                                                                                                               |
| ------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| S3 Objects    | Apply a version scheme to the S3 key/filename. | Ensures that a deployment always receives the same, specific artifact version, even during rollbacks.              |
| ECR Images    | Apply a version scheme to the ECR tag.         | Mutable tags (like `:latest`) can change, leading to inconsistent deployments. Use immutable tags for reliability. |

By enforcing immutable naming, we ensure a deployment to an appliance is always linked to a known-good application version.

### Supported artifact locations

Tensor9 BYOC supports copying artifacts from two locations within the vendor's control:

| Origin Location              | Pros                                                                                      | Cons                                                                                                                                                                                                                                       |
| ---------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Vendor Controller Account    | Tensor9 BYOC manages the necessary permissions for appliances to read and copy artifacts. | Requires the vendor to replicate the artifact into this account before initiating deployment.                                                                                                                                              |
| Another Vendor-Owned Account | Directly reference artifacts where they are used.                                         | Requires the vendor to manually create roles that the Tensor9 BYOC controller can assume to perform the copy operation. May also increase transfer costs by copying once to the Vendor Controller account then on to the customer account. |

### Out-of-scope artifacts

Tensor9 BYOC does not treat the following as artifact sources:

* Secrets (handled by Tensor9 BYOC Secret Management)
* Code repositories (GitHub, CodeCommit, etc.)
* Package mirrors (Maven, NPM, etc.)
* Database data

**Note**: You can, however, export data from these sources as inert files (e.g., a database snapshot) and copy them as S3 objects.

## Delivering an artifact into a git repository

Both artifact kinds above are delivered to a place your application reads from. Some
destinations cannot be read from: a hosted build service that builds your application from a git
repository has to be pushed to, and nobody is present inside your customer's account to do the push.

For that case, the appliance itself pushes an artifact's contents into a git repository in the
customer's account as a commit, and the build service builds from what lands there. The artifact is
still an ordinary object-store file; only its destination and the party that moves it are different.
See [Delivering Artifacts to Git](/byoc/fundamentals/artifact-git-delivery).
