Inspiration

Car makers now have to report the carbon footprint of everything they buy, so they ask every supplier for the footprint of every part, in a fixed format (the PCF data model), shared through a data space instead of by e-mail. In a data space every company runs a connector: you keep your data, publish an offer with rules, and another company's connector must accept those rules before it gets anything.

For a big company that is a project. For Anke, who runs a 40-person metal-stamping shop (fictional, like every company in our demo), it is a wall: the format has about 90 fields, her consultant sent her a spreadsheet with German headers and grams mixed with kilograms, and the rules are written in a policy language she has never seen. Worse, nobody tells her which of her wishes the software actually enforces and which only sit in a contract.

What it does

ClauseSpace walks a first-time supplier through four steps, in about three minutes:

  1. Your data: NVIDIA Nemotron reads the column names of her spreadsheet (never her numbers) and matches each one to a field of the PCF data model. Code checks every match and does all the arithmetic: grams to kilograms, "per kg" to "per piece", dates, country names. Every carbon value needs her click to confirm.
  2. A few questions: only what her sheet doesn't say, each with a plain explanation, where to find the answer and a suggested value. The result is validated against the official PCF v9.0.0 schema.
  3. Your wishes: she writes in her own words, e.g. "Only Arventa and Brennholt may see our footprints. They must delete everything at the end of 2027." Nemotron splits the text into wishes and matches each to a clause from a fixed list. Code then sorts each wish into one of three honest buckets:
    • Checked by the connector: the connector refuses anyone who breaks it;
    • Binding through the agreement: part of the contract, but nobody checks it automatically;
    • Not protected: nothing can enforce it, and we say so instead of pretending.
  4. Live requests: the offer goes into a real connector. She then plays three other companies, each asking from its own connector. Her customer gets an agreement; a data broker is refused by her partner list; a foundry that isn't a member is refused for membership. Every refusal shows the connector's own reason.

How we built it

  • AI: NVIDIA Nemotron 3.5 Lightning on Nebius Token Factory (EU region). One client handles every call, with strict JSON-schema output that code always validates with Pydantic, one retry, and a 60-second timeout.
  • The model only proposes; code decides. The policy sent to the connector is built by code from a closed list of clauses, never written by the model. Every quote must appear in the user's own text, and companies are matched by exact name only.
  • Privacy by design: a routing guard blocks any call with supplier data to a model outside the EU, before it reaches the network. The model sees column headers and made-up example values, never the rows.
  • Real connectors: four Eclipse Dataspace Components (EDC 0.18.1) runtimes in Docker (one provider, three consumers), with our own Java policy functions for the partner list, membership and framework agreement, plus a decision log, so the page can show why a request was refused.
  • An honesty test: for every clause we label "checked by the connector", it proves the connector refuses a request that breaks it; for every "binding" clause, it proves the clause never changes the outcome.
  • Web app: FastAPI with server-rendered pages that work without JavaScript, plus a "Stats for nerds" switch that shows every model call (model, region, tokens, cost) and the exact policy sent.
  • Tests: 272 Python tests and 32 JUnit tests.

Challenges we ran into

  • Choosing the model. Our first default, Nemotron 3 Nano, sometimes spent its whole output budget on reasoning, or invented columns that weren't in the file. Turning reasoning off, naming every column explicitly in the prompt, and switching to Nemotron 3.5 Lightning brought the mapping to one call of about 5-20 seconds, with 22-25 of 25 columns right on our sample.
  • Connectors that stay silent. EDC ignores policy rules it has no function for, and the consumer only learns "refused". We refuse unknown rules before publishing, and added a provider-side decision log for the real reason.
  • A shared demo connector. Every visitor publishes into the same provider, so we had to withdraw old offers on republishing, filter each visitor's view to their own requests, and read catalogues by offer ID (EDC returns 50 offers per page by default).
  • Keeping the AI honest about data: a review caught real cell values leaking into a repair prompt. The model now gets only "column -> field: kind of problem".

Accomplishments that we're proud of

  • The "not protected" bucket. It is easy to build a tool that makes every wish look safe. ClauseSpace tells the supplier the truth, and our honesty test checks that claim against the real connector.
  • The whole flow is real: a valid PCF document, a real connector, a real refusal.

What we learned

  • With a small model, a precise prompt and code-side checks matter more than a bigger model.
  • In data spaces, "the contract says so" and "the software enforces it" are very different things, and users deserve to know which one protects them.

What's next

  • Deploy on Nebius for public testing.
  • Real identity credentials instead of simulated memberships.
  • More clause types, and tagging each connector decision with its offer.
  • Other footprint formats and more languages for spreadsheet headers.

Built With

  • css
  • docker
  • docker-compose
  • eclipse-dataspace-components
  • fastapi
  • gradle
  • html
  • httpx
  • java
  • jinja
  • jsonschema
  • nebius-token-factory
  • nemotron-3.5-lightning
  • nvidia-nemotron
  • openai-sdk
  • openpyxl
  • pydantic
  • pytest
  • python
Share this project:

Updates