Skip to main content

Technical

How ARPI keeps its numbers honest

Synthetic-only data, no personal data by construction, declared grains, documented lineage, reconciliation that proves rather than asserts, a read-only reporting role, and scope gates that block work rather than describe it.

  • Synthetic data onlyComplete
  • No personal data, by constructionComplete
  • Declared grain on every factComplete
  • Reporting role confined by testComplete
  • Reconciliation as a controlComplete
  • Gate 2 CLOSEDClosed

This project contains no real data, and never will

Every warehouse record in this project is synthetic. Granite Auto Group and its three stores are fictional. No real dealership, customer, employee or lending data exists anywhere in the project.

Every figure comes from documented rules and a fixed random seed. Nothing here may be read as, compared against, or cited as the performance of any real automotive retailer.

One exception, and it is named rather than absorbed

The inventory shown on the dealership pages and in the inventory explorer is not machine-generated, and this project does not claim it is.

Synthetic warehouse

Machine-generated
  1. Seeded generatorsDocumented rules, fixed seed
  2. Validation and loadRejections retained
  3. Warehouse and reportingEvery operating figure

No row of it was ever observed anywhere, so it describes no real dealership and supports no comparison with one.

Reference listings

Observed, then de-identified
  1. Private workbookNever enters the repository
  2. SanitizerRemoves VINs, URLs, addresses, dealership identity
  3. Reference treeNever the generated-sample tree
  4. Build-time gateRefuses to write a file still carrying an identifier

Calling this lane synthetic would claim more sanitization than was performed, so it is not called synthetic anywhere on this site.

The inventory shown on this site is sanitized public reference data, not a dealer management system export and not machine-generated. Real VINs, source URLs, listing keys, street addresses and real dealership identity were removed before the workbooks entered this repository; the vehicle attributes that remain are a de-identified snapshot of what a public listing source exposed. Every row describes a listing that was visible at capture time. None of them describes a sale, a delivery, a gross figure or a dealership result.

An inventory summary is descriptive evidence about a reference dataset. It is not an analytical finding about dealership performance, and publishing it does not open Gate 2 or complete the case study.

The trust framework

Five layers, each with something that enforces it

Select a layer to see the controls it holds and the file that implements each one. A control with no enforcement mechanism is a preference, and this page distinguishes the two.

The data itself

The strongest privacy control available is not collecting the attribute. Every prohibited field in this project was never designed, so there is nothing to mask, redact or leak.

Prohibited by construction

These attributes are not redacted. They do not exist in the model.

Data minimisation here means the column was never designed, not that it is masked. A masked column can be unmasked; a column that does not exist cannot leak.

Fairness and interpretation

The limits are on the measure, not in a footnote somewhere else.

A limitation recorded only in a separate document is a limitation nobody reads at the moment it matters. In this project the caution travels with the KPI: it is a required field in the catalogue, it is rendered on the KPI catalogue page, and it is part of the measure's description in the semantic model.

KPI_CATALOG.mdinterpretation caution per KPIView KPI_CATALOG.md (interpretation caution per KPI) on GitHub (opens in a new tab)

Employee scorecards carry context or they do not ship

Volume alone never ranks a person. A high-volume salesperson may show weak gross retention, poor follow-up, heavy discounting, or simply favourable lead routing. Any view that displays employee results must state how it shows lead quality, store traffic, tenure and vehicle mix alongside the number.

In the repositoryARCHITECTURE.md section 23

Attribution is first-touch, and that is a limitation

A lead is credited to the source that produced it, once. Multi-touch journeys are not modelled, so a campaign that assisted a sale without originating the lead receives no credit. This is a deliberate simplification of a genuinely hard problem, and marketing return figures must be read with it in mind.

In the repositoryKPI-MKT-003 interpretation caution

Correlation is never presented as causation

The synthetic generators contain correlations because a plausible dataset needs them. Those correlations were written by the generator, so no finding drawn from this data may claim that one thing causes another - in the data or in the industry. This is why the project draws no conclusion about automotive retail at all.

In the repositoryLIMITATIONS.md

The action queue is deterministic, and there is no model in it

A versioned YAML rule file evaluated against the published datasets. No language model, no learned model, no scoring heuristic: every word comes from a rule template and every number from an exported column, so any action can be recomputed by hand. Evaluated once at export time, so the queue is identical for every visitor of a dataset version, and stateless: nothing is assigned, acknowledged or completed.

In the repositoryconfig/dashboard/action_rules.yaml

A rule change is a data change

Editing a review threshold changes the queue even though no business fact moved. The manifest therefore records the ruleset's hash, and the export check re-derives the queue and fails if the committed one differs. Every threshold the rule file owns is a project default for a fictional dealer group, never an industry benchmark, an OEM standard or a compliance requirement.

In the repositoryscripts/export_dashboard_dataset.py --check

Deferred domains produce no conclusions

F&I penetration, customer retention, service-to-sales opportunity and target attainment all depend on facts that have not been built. No result requiring a deferred fact may be published, which rules those four subjects out of any finding until the facts exist.

In the repositoryKPI_CATALOG.md section 35

The gate system

Gates that block work, evaluated in writing

A gate is opened by a written review that evaluates each of its conditions against a query or a test, not by a decision made on the way to starting the next thing. Two of the four gates are relevant now.

GATE 1

Gate 1 - Power BI development may begin

OPEN
  1. Met: Fact grains are approved

    Every MVP fact declares one grain, enforced by a UNIQUE constraint and covered by tests/integration/test_schema_objects.py.

  2. Met: Dimensions are documented

    All eight MVP dimensions are specified in DATA_DICTIONARY.md with a source-to-target mapping each under docs/source-to-target/.

  3. Met: KPI formulas are documented

    All 29 governed KPIs carry a formula, an explicit numerator and denominator, a grain and a null rule in KPI_CATALOG.md.

GATE 2

Gate 2 - the public analytical case study may begin

CLOSED
  1. Not met: Core Power BI report pages are complete

    powerbi/ARPI_Performance_Intelligence/ARPI_Performance_Intelligence.Report/ is a PBIR shell: a .platform file and a definition.pbir pointing at the semantic model. It contains no page, no visual and no bookmark. Delivered by P2.2.

  2. Not met: SQL and Power BI totals reconcile

    The SQL side exists as powerbi/validation/sql_baseline.json. The Power BI side requires a refreshed model, and no engine has refreshed it. Delivered by P2.2-10.

  3. Not met: Executive findings are drafted

    docs/findings/ is empty. Delivered by P2.3.

No readiness review has been written for this gate yet, which is itself why it is closed. Absence of evidence closes a gate and never opens one.

Secrets and access

Nothing in this repository can be run by finding a password in it.

The database password is never read from a configuration file - only from an environment variable. Continuous integration runs to completion on a fork with zero repository secrets configured, and the only credential anywhere in the workflow is the throwaway password of a container that lives and dies inside one job.

Three roles, and the reporting role is provably confined

arpi_admin owns the objects, arpi_loader writes the pipeline layers, and arpi_reporter reads the reporting schema. The reporter's inability to read raw, staging, warehouse or audit is asserted end to end by a test that attempts each read and requires it to fail - not described in a grants script and hoped for.

In the repositorytests/integration/test_reporter_role_end_to_end.py

A secret check runs on every push

A safety net rather than a full scanner: it fails the build if a tracked file looks like it holds a credential - a committed .env, a live connection string with an embedded password, or a private key. The manifest generator that feeds this website applies the same patterns to its own output and refuses to write a file that matches one.

In the repositoryscripts/check_secrets.py

58 reconciliations, and every critical one has been seen to fail

A check that has never failed is a check nobody has tested. Every critical reconciliation rule in this project has been run against a deliberately corrupted fixture and observed to fail, which is the only way to know it would catch the thing it exists to catch.

In the repositorytests/integration/test_reconciliations.py