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:
- A bundle is deployed to an environment
- The bundle's IaC code executes (Terraform, Helm, etc.)
- Upon successful completion, the bundle outputs artifact data using the
massdriver_artifactresource or provisioner-specific mechanisms - Massdriver validates the artifact data against the artifact definition schema
- The artifact is stored, encrypted, and made available to other packages
Imported Artifacts:
- A user or service account creates an artifact via the Massdriver API or UI
- The artifact type (artifact definition) is specified
- The artifact data and specs are provided
- Massdriver validates against the artifact definition schema
- The artifact is stored and made available for connections
Connection and Consumption
Once an artifact exists, it can be connected to packages:
- 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)
- Connection Establishment: If types match, a connection is created linking the artifact to the package's connection field
- Data Injection: During deployment, the artifact's data is injected into the package's IaC execution context
- 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
namefield 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 namedauthentication) - 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:
- Navigate to
Artifactsin the sidebar - Select the artifact you want to reference
- Click
Copy Artifact IDin 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:
- Nominal Typing: The system checks if the source artifact's type matches the destination connection's expected type, even before any data exists
- Structural Matching: Once the artifact is provisioned, the system validates that the actual data structure matches the schema
- Prevention of Invalid Connections: You cannot connect incompatible artifact types (e.g., a
postgresqlartifact to aredisconnection)
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
datafield - The structure of the
specsfield - 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
artifactssection - 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"
}
}
}
Related Documentation
- Artifact Definitions - Learn about the schemas that define artifact structure
- Bundles - Understand how bundles produce and consume artifacts
- Connecting Bundles - Step-by-step guide to using artifacts
- Custom Artifact Definitions - Create your own artifact definitions
- Artifact Definitions Repository - Browse standard artifact types