Concepts
Audit & provenance
Every quote is re-derivable. Audit blob, provenance chain, conformal intervals, immutability.
ARCNM quotes are defensible. Every cost field traces back to:
- Which input the feature came from (3D geometry, drawing, or both).
- Which process the time estimate was computed for (milling, turning, sheet-metal forming, etc.).
- Which source supplied the rate (manual override, parent environment, environment calibration, platform default).
- Which calibration run produced the active coefficients, on what evidence, at what timestamp.
When a procurement team asks "how did this part get to €12.84?", the audit blob answers in 30 seconds, not a week.
The audit blob
GET /api/v1/parts/calculations/{id} returns the result + a deep
analytics object. The audit blob lives at:
analytics.cost_pipeline
with one section per stage that ran (extraction, drawing,
fusion, planning, physics, cost_decomposition).
The
analyticsblob is free-form and its internal field names are illustrative — treat it as informational and don't hardcode the exact shape. The stable top-level fields (unit_cost,total_cost,setup_cost,currency,status, timestamps) are documented in the Calculations reference.
Top-level structure
{
"id": "9d3f…",
"status": "succeeded",
"unit_cost": 12.84,
"currency": "EUR",
"analytics": {
"cost_pipeline": {
"engine_version": "2026-05-21",
"schema_version": "v2",
"wallclock_s": 32.4,
"stages": {
"extraction": { /* … */ },
"drawing": { /* … */ },
"fusion": { /* … */ },
"planning": { /* … */ },
"physics": { /* … */ },
"cost_decomposition": { /* … */ }
},
"provenance": { /* per-parameter resolved-source map */ },
"intervals": { /* conformal intervals at each stage */ }
}
}
}
Per-stage extracts
Extraction (stages.extraction)
{
"envelope_mm": { /* … */ },
"features": [ /* … */ ],
"dfm_issues": [ /* … */ ],
"material_classification": { "iso_group": "P" },
"wallclock_s": 4.1
}
Drawing (stages.drawing)
Carries the typed DrawingExtraction + per-field confidence +
validation report.
{
"extraction_tier": "arcnm",
"extraction_tier_display": "ARCNM",
"wallclock_s": 21.0,
"drawing_extraction": { /* typed DrawingExtraction */ },
"validation_report": [
{
"rule_id": "R-ISO286-001",
"severity": "confidence_adjust",
"field_path": "pmi_supplements[3]",
"message": "Tolerance pair (+25.0/-0.0 µm) disagrees with ISO 286 lookup (+21/0 µm) for j6.",
"value": [25.0, 0.0],
"expected": [21, 0],
"clause": "ISO 286-1 §A",
"confidence_factor": 0.5
}
],
"self_correction": [ /* per-field retry log */ ]
}
Validation rule_ids are stable: R-ISO286-001/002, R-ISO2768-001/002,
R-Y14_5-001..010, R-TB-001/002/003, R-CHM-001, R-RAD-001,
R-Ra-001/002/003, R-THD-001/002, R-MAT-001. Switch on them in
your downstream pipelines.
Physics (stages.physics)
For each operation, the cost inputs the engine consumed (each resolved through the environment cascade) and the times produced:
{
"operations": [
{
"operation_id": "op_a8…",
"process": "drilling",
"feature_id": "feat_92…",
"inputs": {
"tool_diameter_mm": 8.0,
"feed_rate_mm_per_rev": { "value": 0.18, "source": "platform_default" },
"cutting_speed_m_per_min": { "value": 35.0, "source": "environment_override" }
},
"outputs": {
"setup_time_s": 42.0,
"cycle_time_s": 18.5,
"tool_life_units": 850
}
}
]
}
Cost decomposition (stages.cost_decomposition)
{
"decomposition": { /* per-line-item costs — see Cost concepts */ },
"lot_size_curve": { /* points across batch sizes */ }
}
The conservative tenant-specific adjustment that calibration applies is recorded here too, with its supporting evidence, so every quote stays auditable.
Provenance map
analytics.cost_pipeline.provenance is a flat map from parameter path
to the source that resolved it:
{
"milling.feed_rate_mm_per_rev": "environment_calibration",
"milling.cutting_speed_m_per_min": "environment_override",
"labour_rate_eur_per_hour": "platform_default",
"machine_rate_eur_per_hour.haas_vf2":"environment_override",
"material.steel.1.0577.eur_per_kg": "environment_catalogue"
}
Run jq on it to assert at deploy time:
arc calc get $CALC | jq '.analytics.cost_pipeline.provenance | with_entries(select(.value == "platform_default"))'
# Empty list = every parameter is calibrated, no defaults leaking in.
Immutability
Every successful calculation row is append-only:
- The audit blob is stored as-is in versioned, lifecycle-managed object storage.
- The row's
analyticsfield is read-only after the worker writes it. - Re-running the same
part_revision_id + costing_environment_id + lot_size + materialis not idempotent — it creates a new Calculation row with a new id, so calibration changes are visible. - The previous row stays accessible by id forever.
For "the price as it was on 2026-05-28" queries, persist the
calculation_id in your ERP and re-fetch from us — we keep them.
Conformal intervals
Three levels of interval:
| Level | Field | Width depends on |
|---|---|---|
| Per-parameter | inputs.<key>.interval |
Calibration sample count + spread |
| Per-operation | outputs.<key>.interval |
Propagated from the input intervals it depends on |
| Quote-level | unit_cost_interval_eur |
Combined platform + environment evidence (conservative) |
Where platform and environment evidence both apply, ARCNM reports a conservative interval rather than the tightest one it could — by design (see Calibration → Conformal intervals).
Compliance & retention
- HGB §257 / GoBD: 10-year retention on audit blobs for German customers.
- GDPR: no personal data in the audit blob by construction; only CAD-derived geometry and pricing math.
- SOC 2: audit entries are part of the SOC 2 control set. Read them
via the
auditAPI with theaudit:readscope.
Exporting to your data warehouse
The audit API returns audit rows with cursor pagination — page
through them and drop into Snowflake / BigQuery / Postgres for cost
analytics. Requires the audit:read scope; narrow the stream with the
available action and resource-type filters.
See also
- Calculations — the
analyticsblob is returned byGET /parts/calculations/{id}. - Concepts → Calibration — where the provenance sources come from.
- API → Calculations — fetching the full blob.