Skip to main content

Artifacts

Overview

Artifacts are structured outputs produced by bundles that represent cloud resources and their configuration. They serve as the output of infrastructure provisioning and the input connections to downstream bundles, enabling type-safe composition of infrastructure components.

Artifacts are the bridge between bundles—they allow one bundle's outputs to become another bundle's inputs, creating a composable infrastructure architecture where complex systems are built by connecting simple, reusable components.

Artifacts Enable Infrastructure Composition

Artifacts solve a fundamental challenge in infrastructure management: how to safely pass state and configuration between different infrastructure components, often written in different tools (Terraform, Helm, Bicep, etc.), while maintaining type safety and security.

Instead of manually copying connection strings, credentials, and resource identifiers between components, artifacts provide a standardized, validated contract. When a PostgreSQL bundle provisions a database, it produces a postgresql artifact containing connection details. An application bundle can then consume this artifact as a connection, automatically receiving the correct database hostname, port, and credentials—all validated against the artifact definition schema.

Artifact Structure

Every artifact contains two top-level fields that serve distinct purposes. The specific contents of data and specs are defined by the artifact definition that the artifact conforms to. You decide what data comprises your abstraction (e.g., what makes up "postgresql" for your organization) and what specs about that resource you want available in the platform.

data - Secure, Encrypted Information

Type: object (encrypted at rest)
Purpose: Contains sensitive information about the provisioned resource

The data field stores encrypted, sensitive information that is only accessible to authorized packages. This typically includes:

  • Connection credentials: Database passwords, API keys, authentication tokens
  • Cloud resource identifiers: Resource ARNs, IDs, endpoints
  • IAM configuration: Policy documents, role ARNs, service account configurations
  • Network configuration: Private endpoints, security group IDs, VPC information

Example:

{
"data": {
"authentication": {
"hostname": "db.example.com",
"port": 5432,
"username": "app_user",
"password": "encrypted_secret_value",
"ssl": true
},
"iam": {
"role_arn": "arn:aws:iam::123456789012:role/db-access-role",
"policy": "{...}"
}
}
}

The data field is encrypted at rest using row-level encryption and is never displayed in the UI or exposed in logs. Only packages that have a valid connection to the artifact can access its data.

specs - Public, Searchable Metadata

Type: object
Purpose: Contains non-sensitive metadata for filtering, searching, and display

The specs field stores public metadata that can be safely displayed in the UI and used for filtering and searching artifacts. This typically includes:

  • Cloud provider information: Region, availability zone, account ID
  • Resource characteristics: Instance size, storage type, feature flags
  • Tags and labels: Environment tags, cost allocation tags, organizational metadata
  • Status information: Resource state, health indicators

Example:

{
"specs": {
"aws": {
"region": "us-west-2",
"account_id": "123456789012"
},
"database": {
"engine": "postgresql",
"version": "15.2",
"instance_class": "db.t3.medium"
},
"tags": {
"Environment": "production",
"Team": "platform"
}
}
}

The specs field is visible in the Massdriver UI, allowing users to search and filter artifacts by region, tags, or other metadata without exposing sensitive connection details.

Artifact Origins

Artifacts can be created in two ways, each with different characteristics and use cases:

Provisioned Artifacts

Origin: Created automatically by deployments during infrastructure provisioning

Provisioned artifacts are the most common type. They are automatically created when a bundle successfully deploys and produces outputs defined in its artifacts section.

Characteristics:

  • Created by deployments during the provisioning process
  • Associated with a specific package and bundle field
  • Identified by package.name_prefix-field (e.g., api-prod-database-1234-instance)
  • Automatically updated when the package is redeployed
  • Can only be updated or deleted by deployments
  • Lifecycle is tied to the package that created them

Example: When a PostgreSQL bundle deploys, it creates a provisioned artifact with field: "postgresql" containing the database connection details.

Imported Artifacts

Origin: Created manually or via API for external resources or cloud authentication

Imported artifacts represent resources that exist outside of Massdriver's provisioning system. They are typically used for:

  • Existing cloud resources: Resources created outside Massdriver that need to be referenced
  • Cloud authentication: AWS IAM roles, GCP service accounts, Azure managed identities
  • External services: Third-party APIs, managed services not provisioned by Massdriver
  • Manual configuration: Resources managed through other tools or processes

Characteristics:

  • Created by service accounts or deployments via API
  • Not associated with a package (no package_id)
  • Identified by their UUID
  • Can be updated or deleted by service accounts or deployments
  • Independent lifecycle from packages

Example: An imported artifact might represent an existing AWS IAM role that was created manually and needs to be referenced by multiple bundles.

Artifact Lifecycle

Creation

Artifacts are created in different ways depending on their origin:

Provisioned Artifacts:

  1. A bundle is deployed to an environment
  2. The bundle's IaC code executes (Terraform, Helm, etc.)
  3. Upon successful completion, the bundle outputs artifact data using the massdriver_artifact resource or provisioner-specific mechanisms
  4. Massdriver validates the artifact data against the artifact definition schema
  5. The artifact is stored, encrypted, and made available to other packages

Imported Artifacts:

  1. A user or service account creates an artifact via the Massdriver API or UI
  2. The artifact type (artifact definition) is specified
  3. The artifact data and specs are provided
  4. Massdriver validates against the artifact definition schema
  5. The artifact is stored and made available for connections

Connection and Consumption

Once an artifact exists, it can be connected to packages:

  1. Type Validation: When a package is linked to an artifact in the UI, Massdriver first validates that the artifact's type matches the package's connection schema (nominal typing)
  2. Connection Establishment: If types match, a connection is created linking the artifact to the package's connection field
  3. Data Injection: During deployment, the artifact's data is injected into the package's IaC execution context
  4. Access Control: Only packages with valid connections can access the artifact's encrypted data

Updates

Provisioned Artifacts:

  • Automatically updated when the source package is redeployed
  • Only the name field can be manually updated (metadata only)
  • Data and specs are managed by the deployment process

Imported Artifacts:

  • Can be updated via API or UI
  • All fields (name, data, specs) can be updated
  • Updates are validated against the artifact definition schema

Deletion

Provisioned Artifacts:

  • Can only be deleted by deployments (when the source package is decommissioned)
  • Deletion is blocked if other packages have active connections to the artifact
  • Automatically deleted when the source package is removed

Imported Artifacts:

  • Can be deleted by service accounts or deployments
  • Deletion is blocked if packages have active connections
  • Must be manually removed

Artifact Identification

Artifacts are identified differently based on their origin:

Provisioned Artifacts

Identified by: package.name_prefix-field

Format: {package_name_prefix}-{artifact_field}

The package name prefix follows the format {project-slug}-{environment-slug}-{manifest-slug}-{suffix}. Note that individual slugs (project, environment, manifest) cannot contain hyphens—hyphens are only used to separate the slug components.

Example:

  • Package name prefix: api-prod-database-1234 (project: api, environment: prod, manifest: database, suffix: 1234)
  • Artifact field: instance
  • Artifact identifier: api-prod-database-1234-instance

Another example:

  • Package name prefix: api-prod-database-1234
  • Artifact field: authentication (if the bundle output field was named authentication)
  • Artifact identifier: api-prod-database-1234-authentication

This format provides:

  • Human-readable, meaningful identifiers
  • Consistency across related artifacts
  • Support for IaC tools that don't maintain state
  • Clear association with the source package

Imported Artifacts

Identified by: UUID

Format: {uuid}

Example: 123e4567-e89b-12d3-a456-426614174000

Imported artifacts use UUIDs because they already have stable external identities and don't need the package-based naming convention.

Artifact ID

Every artifact also has a system-generated UUID (id) that can be used for programmatic access. To find an artifact's ID:

  1. Navigate to Artifacts in the sidebar
  2. Select the artifact you want to reference
  3. Click Copy Artifact ID in the top right corner of the artifact's page

How Artifacts Enable Bundle Composition

Artifacts are the foundation of Massdriver's composable infrastructure model. They enable bundles to work together through a type-safe contract system:

Type-Safe Connections

When you connect two packages in the Massdriver UI, the system validates compatibility using artifact definitions:

  1. Nominal Typing: The system checks if the source artifact's type matches the destination connection's expected type, even before any data exists
  2. Structural Matching: Once the artifact is provisioned, the system validates that the actual data structure matches the schema
  3. Prevention of Invalid Connections: You cannot connect incompatible artifact types (e.g., a postgresql artifact to a redis connection)

Cross-Tool State Transfer

Artifacts enable state to be passed between different IaC tools:

  • Terraform → Helm: A Terraform bundle can provision infrastructure and produce an artifact that a Helm bundle consumes
  • OpenTofu → Bicep: State can flow between different cloud providers and tools
  • Any → Any: The artifact system provides a universal interface for state transfer

Automatic Configuration

Artifacts enable automatic application configuration:

  • Environment Variables: Artifact data can be mapped to environment variables using JQ expressions
  • Secrets Injection: Credentials from artifacts are automatically injected as secrets

Dependency Management

Artifacts enforce proper dependency ordering:

  • Required Connections: Bundles can require specific artifacts, preventing deployment until dependencies are met
  • Visual Dependencies: The UI shows artifact connections as visual links, making infrastructure dependencies clear
  • Deployment Ordering: Massdriver automatically determines deployment order based on artifact dependencies

Artifact Definitions

Artifacts must conform to an artifact definition, which is a JSON Schema that defines:

  • The structure of the data field
  • The structure of the specs field
  • Validation rules and constraints
  • UI display configuration

Artifact definitions ensure that:

  • All artifacts of the same type have consistent structure
  • Type safety is enforced at connection time
  • Invalid data is rejected before deployment

See Artifact Definitions for detailed information about creating and using artifact definitions.

Best Practices

Data vs Specs Separation

Keep sensitive data in data:

  • Credentials, passwords, API keys
  • Private endpoints and connection strings
  • IAM policies and role ARNs
  • Any information that should be encrypted

Keep public metadata in specs:

  • Region, availability zone, account information
  • Resource characteristics (size, type, version)
  • Tags and organizational metadata
  • Status and health information

This separation enables:

  • Secure storage of sensitive information
  • UI display and filtering without exposing secrets
  • Compliance with security best practices

Artifact Naming

For Provisioned Artifacts:

  • Use descriptive field names in your bundle's artifacts section
  • The artifact name should clearly indicate what resource it represents
  • Consider the package name prefix when choosing field names

For Imported Artifacts:

  • Use clear, descriptive names that indicate the artifact's purpose
  • Include context about the resource type and environment
  • Follow organizational naming conventions

Artifact Reusability

  • Design artifact definitions for reuse: Create artifact definitions that can be used by multiple bundles
  • Standardize on common types: Use Massdriver's standard artifact definitions when possible
  • Document artifact contracts: Clearly document what data each artifact provides

Connection Management

  • Use required connections: Mark connections as required when the bundle cannot function without them
  • Validate early: The type system prevents invalid connections, but also validate in your IaC code
  • Handle missing artifacts: Design bundles to gracefully handle optional connections

Security Considerations

  • Principle of least privilege: Only include the minimum necessary data in artifacts
  • Encryption: All artifact data is encrypted at rest—never log or expose artifact data
  • Access control: Be aware that any package with a connection can access the artifact's data
  • Secret rotation: Plan for secret rotation when designing artifact schemas

Examples

PostgreSQL Database Artifact

A PostgreSQL bundle produces an artifact with connection details:

{
"data": {
"authentication": {
"hostname": "prod-db.region.rds.amazonaws.com",
"port": 5432,
"username": "app_user",
"password": "encrypted_password",
"database": "myapp_prod",
"ssl": true
},
"iam": {
"role_arn": "arn:aws:iam::123456789012:role/rds-access",
"policy": "{\"Version\":\"2012-10-17\",\"Statement\":[...]}"
}
},
"specs": {
"aws": {
"region": "us-west-2",
"account_id": "123456789012"
},
"database": {
"engine": "postgresql",
"version": "15.2",
"instance_class": "db.r6g.xlarge"
},
"tags": {
"Environment": "production",
"Team": "platform"
}
}
}

Kubernetes Cluster Artifact

A Kubernetes cluster bundle produces an artifact with cluster connection details:

{
"data": {
"authentication": {
"kubeconfig": "encrypted_kubeconfig_content",
"server": "https://cluster.example.com",
"certificate_authority_data": "encrypted_ca_data"
},
"service_account": {
"name": "massdriver-sa",
"namespace": "default",
"token": "encrypted_token"
}
},
"specs": {
"kubernetes": {
"version": "1.28",
"provider": "eks"
},
"aws": {
"region": "us-west-2"
},
"cluster": {
"node_count": 3,
"node_instance_type": "m5.large"
}
}
}

S3 Bucket Artifact

An S3 bucket bundle produces an artifact with bucket details:

{
"data": {
"bucket": {
"name": "my-app-logs-prod",
"arn": "arn:aws:s3:::my-app-logs-prod",
"region": "us-west-2"
},
"iam": {
"policy": "{\"Version\":\"2012-10-17\",\"Statement\":[...]}",
"role_arn": "arn:aws:iam::123456789012:role/s3-access"
}
},
"specs": {
"aws": {
"region": "us-west-2",
"account_id": "123456789012"
},
"bucket": {
"versioning": true,
"encryption": "AES256",
"lifecycle_rules": true
},
"tags": {
"Purpose": "application-logs",
"Environment": "production"
}
}
}