🛰️ Dagster + Makoto Integration Concept

Asset materialization metadata is already half a DBOM — finish the job with a signed envelope.

Note: This page explores how Makoto Levels could be implemented on Dagster. It is a conceptual integration proposal — illustrative, not a shipped library. The patterns shown use real Dagster APIs; the Makoto pieces are sketches you (or we) could build out.

What is Dagster?

Dagster's asset-first model is uniquely well-suited to Makoto. Every asset materialization already records inputs, partition, code version, and metadata. A small sensor + IO manager turns each materialization into a signed Transform attestation, written alongside the asset.

Software-defined AssetsAsset graph IS the lineage graph
Materialization MetadataAlready structured — wrap in DSSE envelope
SensorsFire attestation post-materialization without code changes
IO ManagersHash on write, verify on read

Integration Approach

Primary pattern: Asset decorator + sensor + IO manager. Below are the integration options ordered by lift required.

How Makoto attaches to Dagster

  • @makoto_asset decorator — Drop-in replacement for `@asset` that emits an attestation on every materialization.
  • Materialization sensor — Listens to `AssetMaterialization` events globally — zero asset changes.
  • MakotoIOManager — IO manager that hashes on write, verifies inbound DBOM on read.
  • Schedule + Job hooks — Job-level `on_success` writes a job-scoped DBOM combining all asset attestations.

Conceptual Code Example

Concept: Dagster asset with Makoto attestation

Materialization metadata is the attestation payload — one decorator and done

from dagster import asset, AssetExecutionContext, MetadataValue
from makoto_dagster import makoto_asset, MakotoIOManager

@makoto_asset(
    level=2,
    deps=["raw_orders"],
    io_manager_def=MakotoIOManager(
        bucket="curated-data",
        signing_key_id="kms://aws/key/...",
    ),
)
def curated_orders(context: AssetExecutionContext, raw_orders):
    """Hash PII, keep paid orders only."""
    df = raw_orders.assign(
        email_hash=raw_orders.email.apply(sha256)
    )
    df = df[df.status == "paid"].drop(columns=["email"])

    context.add_output_metadata({
        "row_count": MetadataValue.int(len(df)),
        "columns":   MetadataValue.json(list(df.columns)),
        # @makoto_asset auto-adds:
        #   - dbom.content_hash
        #   - dbom.upstream_digests (from raw_orders)
        #   - dbom.signature
    })
    return df

# On materialization:
#   1. MakotoIOManager hashes the dataframe → content_hash
#   2. context dependency digests pulled from prior materializations
#   3. DSSE envelope signed via configured key
#   4. Persisted to bucket alongside the parquet file

Potential Use Cases

Asset-graph Audits

The lineage graph IS the DBOM graph — auditors traverse it directly.

Partition-level Trust

Each daily partition gets its own attestation.

Cross-team Asset Sharing

Downstream teams subscribe only to assets with valid issuer DBOMs.

ML Asset Provenance

Models, features, and predictions all sit on the same attested graph.

Interested in Dagster + Makoto?

This is a conceptual integration. If you're shipping Dagster pipelines and want to add Makoto attestations, open an issue or reach out — we'd love to scope a real implementation.

Learn about Dagster Read Makoto Spec All Integrations