Chapter 21 · Data Marts, Domain Data Products, Self-Service Analytics, and Ownership

Design a Marketing/Finance/Operations Mart Strategy that Reuses Conformed Data Without Blocking Domain Delivery

Assemble marketing, finance, and operations marts over the same governed AtlasMart core, detect and repair semantic drift, then document a domain strategy that preserves autonomy without creating silos.

Intermediate → Advanced190–235 minutesComplete domain mart strategy lab10 lines · 8 orders · 820 USDLast reviewed: September 2026

Learning outcomes

01

Implement the complete local AtlasMart mart/certification fixture.

02

Build finance, marketing, and operations outputs from shared governed assets.

03

Reproduce and detect deliberate semantic drift in a sandbox.

04

Run a blocked promotion, repair the dependencies, and run a successful certification.

05

Reconcile domain outputs to enterprise controls and document the production strategy/limitations.

Continuity and explicit mart-layer addition

Chapter 21 begins from Chapter 20's governed warehouse/semantic truth: 10 current paid lines, 8 orders, 12 units, 820 USD gross revenue, 495 USD cost, and 325 USD gross profit. The canonical fact grain remains one current paid order line. The active semantic contracts remain gross_revenue_usd.v1, active_customers.v1, and period_retention.v1. This chapter does not redefine those facts or metrics. It adds domain delivery surfaces—marts, data products, sandboxes, and certified outputs—whose shared concepts must inherit the governed contracts.

Lab contract

Runtime: Python standard library plus SQLite; generation evidence uses the local runtime reported by the script. Environment: local/in-process, synthetic, and no-cost. Storage: one SQLite file plus JSON evidence; views stand in for dependent marts. Source: the Chapter 20 AtlasMart fact/dimension fixture. Time: warehouse order_date semantics remain UTC and are not silently converted. Currency: governed gross revenue is USD-only. Security: access-class labels are metadata in this lab, not database-enforced authorization; production enforcement belongs in the warehouse/semantic/security stack. History: existing SCD/history semantics are unchanged. Portability: the mart concepts are vendor-neutral; view syntax, catalog metadata, masking, policy enforcement, and materialization are engine-specific.

1. Final design: federated delivery on a conformed core

Target strategy
governed warehouse + semantic contracts        |        +--> finance mart     (revenue, cost, profit)        +--> marketing mart   (customer/segment/geography + governed revenue)        +--> operations mart  (orders, units + operational extensions)        |        +--> self-service sandboxes                 |                 +-- promotion gate --> certified domain productshared concepts: inherited + versioneddomain-only concepts: domain-owned + documentedcertification: evidence-based, not schema-name-based

2. Run the complete deterministic lab

Save the following as ch21_lab.py and run it with your local Python interpreter. It creates only /mnt/data/atlasmart_ch21_lab in this generation environment; on your machine change OUT to a convenient local directory if desired.

ch21_lab.py
from __future__ import annotationsimport hashlib, json, sqlite3, sysfrom pathlib import PathOUT=Path('/mnt/data/atlasmart_ch21_lab'); OUT.mkdir(parents=True,exist_ok=True)DB=OUT/'atlasmart_ch21.sqlite'if DB.exists(): DB.unlink()SALES=[('O1001',1,'2026-09-18','P100','C001','web',2,10000,6000,'USD','paid'),('O1001',2,'2026-09-18','P200','C001','web',1,2500,1500,'USD','paid'),('O1002',1,'2026-09-18','P300','C002','mobile',1,19000,12000,'USD','paid'),('O1003',1,'2026-09-19','P400','C001','web',1,10000,6500,'USD','paid'),('O1005',1,'2026-09-20','P100','C004','mobile',1,5000,3000,'USD','paid'),('O1005',2,'2026-09-20','P400','C004','mobile',1,10000,6500,'USD','paid'),('O1007',1,'2026-09-21','P300','C003','sales',1,7500,4500,'USD','paid'),('O1008',1,'2026-09-21','P200','C002','mobile',2,5000,2500,'USD','paid'),('O1009',1,'2026-09-22','P100','C005','web',1,5000,2500,'USD','paid'),('O1010',1,'2026-09-22','P100','C003','sales',1,8000,4500,'USD','paid')]CUSTOMERS=[('C001','D-CUST-001','Ada Retail','Mid-Market','G-NORTH','active'),('C002','D-CUST-002','Ben Home','Consumer','G-EAST','active'),('C003','D-CUST-003','Cyra Labs','Enterprise','G-EAST','active'),('C004','D-CUST-004','Dara Studio','Consumer','G-SOUTH','inactive'),('C005','D-CUST-005','__INFERRED__','__UNKNOWN__','__UNKNOWN__','active')]PRODUCTS=[('P100','Keyboard','Accessories'),('P200','Mouse','Accessories'),('P300','Monitor','Displays'),('P400','Dock','Accessories')]METRIC_HASHES={'gross_revenue_usd.v1':'6be77e930e087257e5756fc2c9ccddd4293fed6a457d3a8c72badef65dad5e8a','active_customers.v1':'1fb6a9bb4c820d321fe786b0809124fa279182c0f6a28e81db1194f37ada1eb0','period_retention.v1':'66e7840903abf5f871d39f72c35935d3d98cbadb8496480342f781777da3a962'}EXPECTED={'lines':10,'orders':8,'units':12,'revenue_usd':820,'cost_usd':495,'profit_usd':325}def h(v): return hashlib.sha256(json.dumps(v,sort_keys=True,separators=(',',':')).encode()).hexdigest()def setup(): c=sqlite3.connect(DB) c.executescript(''' PRAGMA foreign_keys=ON; CREATE TABLE fact_sales(order_id TEXT,line_no INT,order_date TEXT,product_id TEXT,customer_id TEXT,channel TEXT,quantity INT,amount_cents INT,cost_cents INT,currency_code TEXT,status TEXT,PRIMARY KEY(order_id,line_no)); CREATE TABLE dim_customer(customer_id TEXT PRIMARY KEY,durable_customer_id TEXT,customer_name TEXT,segment TEXT,geography_code TEXT,lifecycle_status TEXT); CREATE TABLE dim_product(product_id TEXT PRIMARY KEY,product_name TEXT,category TEXT); CREATE TABLE metric_registry(metric_name TEXT PRIMARY KEY,spec_hash TEXT NOT NULL,status TEXT NOT NULL,owner TEXT NOT NULL); CREATE TABLE mart_registry(mart_name TEXT PRIMARY KEY,domain TEXT,owner TEXT,status TEXT,certified_at TEXT,access_class TEXT,contract_hash TEXT); CREATE TABLE mart_dependency(mart_name TEXT,upstream_object TEXT,dependency_type TEXT,PRIMARY KEY(mart_name,upstream_object)); CREATE TABLE promotion_check(run_id TEXT,mart_name TEXT,check_name TEXT,result TEXT,evidence TEXT,PRIMARY KEY(run_id,mart_name,check_name)); ''') c.executemany('INSERT INTO fact_sales VALUES (?,?,?,?,?,?,?,?,?,?,?)',SALES) c.executemany('INSERT INTO dim_customer VALUES (?,?,?,?,?,?)',CUSTOMERS) c.executemany('INSERT INTO dim_product VALUES (?,?,?)',PRODUCTS) for n,sh in METRIC_HASHES.items(): c.execute('INSERT INTO metric_registry VALUES (?,?,?,?)',(n,sh,'active','enterprise-semantic')) c.commit(); return cdef controls(c): r=c.execute("SELECT count(*),count(distinct order_id),sum(quantity),sum(amount_cents),sum(cost_cents),sum(amount_cents-cost_cents) FROM fact_sales WHERE status='paid' AND currency_code='USD'").fetchone() return {'lines':r[0],'orders':r[1],'units':r[2],'revenue_usd':r[3]//100,'cost_usd':r[4]//100,'profit_usd':r[5]//100}def build_dependent_marts(c): c.executescript(''' DROP VIEW IF EXISTS mart_finance_daily; CREATE VIEW mart_finance_daily AS SELECT order_date, SUM(amount_cents)/100.0 AS gross_revenue_usd,        SUM(cost_cents)/100.0 AS cost_usd, SUM(amount_cents-cost_cents)/100.0 AS gross_profit_usd FROM fact_sales WHERE status='paid' AND currency_code='USD' GROUP BY order_date; DROP VIEW IF EXISTS mart_operations_daily; CREATE VIEW mart_operations_daily AS SELECT order_date, COUNT(DISTINCT order_id) AS orders, SUM(quantity) AS units FROM fact_sales WHERE status='paid' GROUP BY order_date; DROP VIEW IF EXISTS mart_marketing_customer_daily; CREATE VIEW mart_marketing_customer_daily AS SELECT f.order_date,f.customer_id,c.segment,c.geography_code,        SUM(f.amount_cents)/100.0 AS governed_revenue_usd FROM fact_sales f JOIN dim_customer c USING(customer_id) WHERE f.status='paid' AND f.currency_code='USD' GROUP BY f.order_date,f.customer_id,c.segment,c.geography_code; DROP VIEW IF EXISTS mart_marketing_wide; CREATE VIEW mart_marketing_wide AS SELECT f.order_date,f.order_id,f.line_no,f.customer_id,c.customer_name,c.segment,c.geography_code,        f.product_id,p.product_name,p.category,f.channel,f.quantity,f.amount_cents/100.0 AS governed_revenue_usd FROM fact_sales f JOIN dim_customer c USING(customer_id) JOIN dim_product p USING(product_id) WHERE f.status='paid' AND f.currency_code='USD'; ''') for name,domain,owner,access in [ ('mart_finance_daily','finance','finance-analytics','finance-certified'), ('mart_operations_daily','operations','operations-analytics','operations-certified'), ('mart_marketing_customer_daily','marketing','growth-analytics','marketing-certified'), ('mart_marketing_wide','marketing','growth-analytics','marketing-certified')]:  deps=['fact_sales','gross_revenue_usd.v1'] if 'finance' in name else ['fact_sales']  if 'marketing' in name: deps=['fact_sales','dim_customer','gross_revenue_usd.v1'] + (['dim_product'] if 'wide' in name else [])  contract={'mart':name,'domain':domain,'owner':owner,'dependencies':deps,'access':access}  c.execute('INSERT OR REPLACE INTO mart_registry VALUES (?,?,?,?,?,?,?)',(name,domain,owner,'certified','2026-09-21T11:00:00Z',access,h(contract)))  for d in deps: c.execute('INSERT OR REPLACE INTO mart_dependency VALUES (?,?,?)',(name,d,'governed')) c.commit()def make_bad_sandbox(c): c.executescript('''DROP TABLE IF EXISTS sandbox_marketing_revenue; CREATE TABLE sandbox_marketing_revenue AS SELECT order_date, SUM(amount_cents)/100.0 AS revenue FROM fact_sales WHERE status='paid' AND currency_code='USD' AND channel <> 'sales' GROUP BY order_date;''')def scan_drift(c): governed=c.execute("SELECT SUM(amount_cents)/100.0 FROM fact_sales WHERE status='paid' AND currency_code='USD'").fetchone()[0] bad=c.execute('SELECT SUM(revenue) FROM sandbox_marketing_revenue').fetchone()[0] return {'governed_revenue_usd':governed,'sandbox_revenue_usd':bad,'delta_usd':bad-governed,'status':'DRIFT' if bad!=governed else 'PASS'}def promote(c,run_id,mart_name,repaired=False): checks=[] if repaired:  observed=c.execute('SELECT SUM(governed_revenue_usd) FROM sandbox_marketing_revenue_fixed').fetchone()[0] else: observed=c.execute('SELECT SUM(revenue) FROM sandbox_marketing_revenue').fetchone()[0] checks.append(('metric_reconciliation','PASS' if observed==820 else 'FAIL',f'observed={observed:.2f}; expected=820.00')) checks.append(('metric_version','PASS' if repaired else 'FAIL',f"required gross_revenue_usd.v1 hash={METRIC_HASHES['gross_revenue_usd.v1']}")) checks.append(('conformed_customer','PASS' if repaired else 'FAIL','must consume governed dim_customer rather than team-local customer semantics')) checks.append(('owner','PASS','owner=growth-analytics')) checks.append(('access_class','PASS','access=marketing-certified')) for n,res,ev in checks: c.execute('INSERT OR REPLACE INTO promotion_check VALUES (?,?,?,?,?)',(run_id,mart_name,n,res,ev)) decision='CERTIFY' if all(x[1]=='PASS' for x in checks) else 'BLOCK' return decision,checksdef repair_sandbox(c): c.executescript('''DROP VIEW IF EXISTS sandbox_marketing_revenue_fixed; CREATE VIEW sandbox_marketing_revenue_fixed AS SELECT f.order_date,c.segment,c.geography_code,SUM(f.amount_cents)/100.0 AS governed_revenue_usd FROM fact_sales f JOIN dim_customer c USING(customer_id) WHERE f.status='paid' AND f.currency_code='USD' GROUP BY f.order_date,c.segment,c.geography_code;''') contract={'mart':'marketing_revenue_v1','dependencies':['fact_sales','dim_customer','gross_revenue_usd.v1'],'metric_hash':METRIC_HASHES['gross_revenue_usd.v1'],'owner':'growth-analytics','access':'marketing-certified'} c.execute('INSERT OR REPLACE INTO mart_registry VALUES (?,?,?,?,?,?,?)',('marketing_revenue_v1','marketing','growth-analytics','certified','2026-09-21T11:30:00Z','marketing-certified',h(contract))) for d in contract['dependencies']: c.execute('INSERT OR REPLACE INTO mart_dependency VALUES (?,?,?)',('marketing_revenue_v1',d,'governed')) c.commit(); return contractdef main(): c=setup(); ctl=controls(c); assert ctl==EXPECTED,ctl build_dependent_marts(c) fin=c.execute('SELECT SUM(gross_revenue_usd),SUM(cost_usd),SUM(gross_profit_usd) FROM mart_finance_daily').fetchone(); assert fin==(820.0,495.0,325.0) ops=c.execute('SELECT SUM(orders),SUM(units) FROM mart_operations_daily').fetchone(); assert ops==(8,12) mkt=c.execute('SELECT SUM(governed_revenue_usd),COUNT(DISTINCT customer_id) FROM mart_marketing_customer_daily').fetchone(); assert mkt==(820.0,5) wide=c.execute('SELECT COUNT(*),SUM(governed_revenue_usd) FROM mart_marketing_wide').fetchone(); assert wide==(10,820.0) make_bad_sandbox(c); drift=scan_drift(c); assert drift['sandbox_revenue_usd']==665.0 and drift['status']=='DRIFT',drift bad_dec,bad_checks=promote(c,'PROMO-001','sandbox_marketing_revenue',False); assert bad_dec=='BLOCK' contract=repair_sandbox(c); fixed=c.execute('SELECT SUM(governed_revenue_usd) FROM sandbox_marketing_revenue_fixed').fetchone()[0]; assert fixed==820.0 good_dec,good_checks=promote(c,'PROMO-002','marketing_revenue_v1',True); assert good_dec=='CERTIFY' deps=[dict(zip(['mart_name','upstream_object','dependency_type'],r)) for r in c.execute('SELECT * FROM mart_dependency ORDER BY mart_name,upstream_object')] regs=[dict(zip(['mart_name','domain','owner','status','certified_at','access_class','contract_hash'],r)) for r in c.execute('SELECT * FROM mart_registry ORDER BY mart_name')] checks=[dict(zip(['run_id','mart_name','check_name','result','evidence'],r)) for r in c.execute('SELECT * FROM promotion_check ORDER BY run_id,check_name')] duplicate_scan={  'independent_business_definitions':['sandbox_marketing_revenue.revenue excludes channel=sales but uses generic revenue name'],  'governed_metric_reuse':sorted({r[1] for r in c.execute("SELECT mart_name,upstream_object FROM mart_dependency WHERE upstream_object LIKE '%.v1'")}),  'status':'DRIFT_DETECTED_AND_REPAIRED'} report={'runtime':{'python':sys.version.split()[0],'sqlite':sqlite3.sqlite_version},'controls':ctl,  'domain_mart_results':{'finance':{'revenue_usd':fin[0],'cost_usd':fin[1],'profit_usd':fin[2]},'operations':{'orders':ops[0],'units':ops[1]},'marketing':{'revenue_usd':mkt[0],'customers_all_time':mkt[1]},'wide':{'rows':wide[0],'revenue_usd':wide[1]}},  'drift':drift,'bad_promotion':{'decision':bad_dec,'checks':bad_checks},'repaired_promotion':{'decision':good_dec,'checks':good_checks},  'repaired_contract':contract,'mart_registry':regs,'dependencies':deps,'promotion_evidence':checks,'duplicate_definition_scan':duplicate_scan,  'warehouse_hash':h(SALES),'metric_hashes':METRIC_HASHES} (OUT/'report.json').write_text(json.dumps(report,indent=2,sort_keys=True),encoding='utf-8') (OUT/'dependency_map.json').write_text(json.dumps(deps,indent=2),encoding='utf-8') (OUT/'promotion_checklist.json').write_text(json.dumps(checks,indent=2),encoding='utf-8') print(json.dumps(report,indent=2,sort_keys=True)); c.close()if __name__=='__main__': main()

3. Expected acceptance evidence

Certified mart controls
Finance certified mart  revenue_usd: 820.00  cost_usd:    495.00  profit_usd:  325.00Operations certified mart  orders:      8  units:       12Marketing certified mart  revenue_usd: 820.00  customers:   5Certified wide delivery surface  rows:        10  revenue_usd: 820.00
Drift and promotion outcome
governed gross_revenue_usd.v1:        820.00 USDindependent marketing "revenue":        665.00 USDdelta:                                 -155.00 USDreason: hidden predicate channel <> 'sales'certification decision before repair:   BLOCKcertification decision after repair:    CERTIFY

These outputs prove three separate properties: each certified domain product answers its own bounded questions; overlapping enterprise metrics reconcile to the same governed truth; and a plausible independent sandbox is blocked when it forks shared semantics.

4. Inspect the generated evidence files

Evidence inventory
atlasmart_ch21_lab/  atlasmart_ch21.sqlite  report.json  dependency_map.json  promotion_checklist.jsonreport.json  runtime + warehouse controls  domain mart results  drift evidence  blocked/successful promotion results  registry + contract hashes  dependency graph  duplicate-definition scan

The JSON files are intentionally boring, portable evidence. A production implementation may use a catalog, metadata graph, CI system, warehouse policy engine, or data-product portal, but the evidence requirements remain: what depends on what, which contract version is consumed, what passed, who owns it, and whether shared controls reconcile.

5. Consumer queries at each domain boundary

Finance consumer
SELECT order_date,gross_revenue_usd,cost_usd,gross_profit_usdFROM mart_finance_dailyORDER BY order_date;
Operations consumer
SELECT order_date,orders,unitsFROM mart_operations_dailyORDER BY order_date;
Marketing consumer
SELECT segment,geography_code,SUM(governed_revenue_usd) AS revenue_usdFROM mart_marketing_customer_dailyGROUP BY segment,geography_codeORDER BY segment,geography_code;

The domain interfaces differ by consumer need. What remains the same is the meaning of shared keys and measures.

6. Failure injection and recovery checklist

  1. Recreate the 665 USD independent sandbox and confirm PROMO-001 is BLOCK.
  2. Change the sandbox table name only; verify the decision still blocks—naming is not evidence.
  3. Repair dependencies/metric version and confirm PROMO-002 is CERTIFY.
  4. Re-run the script from a clean directory; hashes and controls should reproduce for the same code/fixture.
  5. Change a shared metric hash without migrating the mart; promotion should fail until the dependency is explicitly updated/tested.
  6. Change a domain-only column; shared revenue should remain 820 USD.

7. What this proves—and does not prove

Proves: on the synthetic fixture, dependent domain marts can expose different grains/shapes while shared revenue stays 820 USD; independent hidden filters create observable drift; certification can block and then accept a repaired artifact. Does not prove: production authorization, distributed catalog consistency, organization-wide stewardship, BI cache invalidation, materialization performance, legal privacy compliance, or universal mart topology. Those depend on platform, scale, policies, and human operating processes.

8. Production decision record

Decision surface AtlasMart rule
Domain autonomy Domains own bounded delivery surfaces and domain-only extensions.
Conformance Shared facts/dimensions/metrics are inherited by version/hash.
Duplication Physical duplication allowed when justified; semantic duplication rejected.
Promotion Sandbox → automated/human evidence gate → certified version.
Access Certified metadata plus real policy enforcement; metadata alone is insufficient.
Change propagation Dependency graph + versioned migration, not silent overwrite.
Discoverability Publish owner, grain, semantics, freshness, quality, lineage, and deprecation state.

9. Correctness, freshness, retry, cost, compatibility, and rollback

Correctness: overlapping domain metrics reconcile to atomic controls. Freshness/history: marts expose upstream watermark/history semantics; current-state dimensions cannot silently replace as-was requirements. Retry/replay: materialization/promotion must be idempotent for artifact+dependency version. Data quality: certification includes row/measure/key/conformance checks. Security/privacy: synthetic identities only here; production uses least privilege, purpose limitation, export controls, and Chapter 22 mechanisms. Observability: product owner, refresh, tests, failures, consumers, and usage are monitored. Performance/cost: persist only when measured value justifies refresh/storage duplication. Compatibility: views/catalogs/RBAC differ by engine; the contracts are vendor-neutral. Rollback: route consumers to the prior certified product/version and preserve failed-promotion evidence.

10. Cleanup/reset

Delete atlasmart_ch21_lab and rerun python ch21_lab.py to recreate the deterministic lab from scratch. No cloud account, external service, repository mutation, or paid resource is required.

11. Bridge to Chapter 22

Chapter 21 introduced ownership and access boundaries but intentionally treated the lab's access classes as metadata. Chapter 22 turns those intentions into security mechanisms: authentication, roles/service identities, row/column policies, masking/tokenization, PII classification, retention, and bypass-path threat modeling.

Knowledge check

Acceptance questions

  1. Why can finance and marketing have different marts but identical revenue?
  2. What exactly causes PROMO-001 to block?
  3. Why is a wide table not automatically an independent mart?
  4. Which parts of the lab are metadata only?
  5. What does Chapter 22 need to add?
Review the answers

1. They inherit the same governed revenue contract while choosing domain-specific shapes.

2. Reconciliation, metric-version, and conformed-customer checks fail.

3. It can be dependent if generated from governed dependencies with preserved semantics.

4. Access-class labels and certification registry do not themselves enforce authorization.

5. Real least-privilege identities/policies, masking, privacy controls, and bypass-path protection.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.