Skip to content
decosa
LiveHostedSelf-hostMac

Check green claims in copy

A table of every environmental claim in your copy: banned, needs evidence or backed, with the rule, the evidence line and a safer rewrite.

Held-out test43/44 (98%)Claims given the right verdict (held-out set, first run)
On production8.6 smedian on production (2026-09-25); slower when the service is busy
List price~$0.80 per 100 piecesmeasured, at list price

Built on: Typed judgment, Grounding, Signed record

Loading the tool…

Use it your way

Use it from your codeThe hosted API with your key, and prompts to paste into a coding agent
Hosted · by Decosa

Get an API key

  • Call the green-claims substantiation check API from your own code in minutes.
  • Every model answer carries a signed receipt.
  • Nothing to install; we run the models.
Self-host · your GPUs

Run it yourself, on request

  • The same open models and app, on 1× RTX PRO 6000 (96 GB) or 1× RTX 5090 (32 GB) for the model; the rulepack, grounding spans and the report run on CPU.
  • Data never leaves your machines, and there are no Decosa charges.
  • One prompt for Claude Code or Codex assembles the whole stack.
  • Early access: the container images are not public yet and the source needs access; the prompt says how to ask.

Build with it

Paste one of these into Claude Code, Codex or another coding agent. The first wires your project to the hosted API with your DECOSA_API_KEY. The second pulls our containers and runs the same stack on your own GPU, with no Decosa charges.

Base URL
https://api.decosa.ai
Auth
Authorization: Bearer $DECOSA_API_KEY (or a demo session token)
Tool id
green-claims-check

Use the hosted API

# Decosa green-claims substantiation check: use the hosted API

You are wiring Decosa's green-claims check into this project. It takes marketing copy (pack text, a product page or an
ad script) and the evidence file behind it (LCA summaries, certificates, offset contracts, plans, policies). For every
sentence it decides whether it is an environmental claim, judges it against the rules that Member States apply from
27 September 2026 under Directive (EU) 2024/825 (or, in UK mode, the CMA Green Claims Code), grounds it in a quoted
span of the evidence when it can, and drafts a rewrite. It returns a CSV claim table, a Markdown report and a report
signed by the server. Every model call has its own signed receipt. Use only what is listed below. If you need
something else, stop and ask me.

- Base URL: `https://api.decosa.ai`
- Health check: `GET https://api.decosa.ai/healthz`.
- This is a triage for a compliance reviewer, not legal advice and never a compliance sign-off. Say so wherever you
  show results, and never label copy "compliant".
- The hosted API is for synthetic or already published copy. Unreleased campaigns and supplier contracts belong on a
  self-hosted box.

## Auth: API key (or a demo session)
1. Preferred: an API key (`dk_…`) from "Get an API key" on the tool page. Keep it in an environment variable,
   `DECOSA_API_KEY`, never in code. Send `Authorization: Bearer $DECOSA_API_KEY`.
2. Without a key: `POST https://api.decosa.ai/demo/session` with `{"vertical": "green-claims-check"}` returns `{"token", "expires_at", "budget"}`.
   Sessions per IP are limited; over a limit you get HTTP 429 with `Retry-After`.
3. A check needs about 420 generated tokens per claim sentence (402 otherwise). One check at a time per demo token.

## Endpoints
- `POST /green/check` (token). Body:
  ```json
  {"copy": {"text": "...", "title": "...", "medium": "pack|web|ad|other"},
   "brand": "optional", "product": "optional", "mode": "eu|uk",
   "evidence": [{"title": "...", "kind": "lca|certificate|offset|plan|policy|other", "text": "..."}]}
  ```
  - Limits: copy up to 8,000 characters and 40 claim sentences; up to 10 evidence files and 200,000 characters in
    total. Send text, not URLs or PDFs: extract the text yourself. Describe a label in words ("[Label: leaf badge
    'EcoPure']"): images are not read. Evidence is optional, but without it nothing can be substantiated.
  - JSON by default: `{status: "banned_claims"|"high_risk"|"needs_work"|"nothing_flagged", counts, rule_counts, mode,
    claims: [{i, text, environmental, verdict, findings: [{verdict, rule, detail}], rules, rule_cites: [{id, cite, short,
    url}], support, confidence, evidence: [{span, source, start, end, role, quote}], rewrite, remove, rewrite_flags,
    reason, support_reason, evidence_reason, receipt_ids}], receipts, report, report_md, table_csv, budget, note}`.
  - Verdicts: `banned` (EU Annex I), `high_risk` (UK mode only), `needs_substantiation`, `substantiated` (only with a
    cited evidence span), `not_environmental`, `not_checked` (a model call failed; never a guessed verdict).
  - With `Accept: text/event-stream` (or `"stream": true`) it streams `ready`, `receipt` events and one `claim` event
    per sentence (not in text order), then `report`, `budget`, `done`.
- `POST /green/verify` (no token) `{"report": {...}, "text"?: "...", "evidence"?: [...], "report_md"?: "...", "table_csv"?: "..."}` →
  `{valid_signature, signed_by_this_server, status, copy_matches?, evidence_matches?, report_md_matches?, table_csv_matches?}`.
- `GET /green/info` (rule ids with the verbatim rule text and source URL, limits, what is not checked),
  `GET /green/samples`, `GET /attest/signing-key`.

Rule ids. EU: `eu-2a` (label without a certification scheme), `eu-4a` (generic claim), `eu-4b` (whole product when only
a part qualifies), `eu-4c` (offset-based neutral or reduced claim), `eu-10a` (legal requirement as a feature),
`eu-6-2-d` (future target without a verified plan; case by case, so never "banned"), `eu-6-1` (a specific claim the
evidence does not back). UK: `uk-a`, `uk-b`, `uk-b-future`, `uk-b-labels`, `uk-b-part`, `uk-c`, `uk-f`.

## Example: check a product page before it is published (Python, `pip install httpx`)
```python
import httpx, os, pathlib
API = "https://api.decosa.ai"
H = {"Authorization": f"Bearer {os.environ['DECOSA_API_KEY']}"}
body = {"copy": {"text": page_text, "title": "Laundry Liquid product page", "medium": "web"},
        "brand": "Fernhollow", "product": "Laundry Liquid", "mode": "eu",
        "evidence": [{"title": "LCA summary 2026", "kind": "lca", "text": lca_text},
                     {"title": "Carbon credit agreement", "kind": "offset", "text": offset_text}]}
r = httpx.post(f"{API}/green/check", json=body, headers=H, timeout=600)
r.raise_for_status()
res = r.json()
pathlib.Path(f"{res['report']['id']}.csv").write_text(res["table_csv"])     # the claim table for the reviewer
pathlib.Path(f"{res['report']['id']}.json").write_text(r.text)            # keep the signed report with the copy
for c in res["claims"]:
    if c["verdict"] in ("banned", "high_risk", "needs_substantiation"):
        print(c["verdict"], c["rules"], c["text"], "->", c["rewrite"] or ("remove" if c["remove"] else "rewrite by hand"))
```

## Verify a report yourself (`pip install cryptography`)
```python
import hashlib, json, urllib.request
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
pub = json.load(urllib.request.urlopen("https://api.decosa.ai/attest/signing-key"))["pubkey"]
rp = res["report"]
assert rp["signer"] == pub
body = {k: v for k, v in rp.items() if k != "sig"}
msg = rp["v"].encode() + b"\n" + json.dumps(body, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()
Ed25519PublicKey.from_public_bytes(bytes.fromhex(pub)).verify(bytes.fromhex(rp["sig"]), msg)
assert hashlib.sha256(page_text.encode()).hexdigest() == rp["copy"]["sha256"]
assert hashlib.sha256(res["table_csv"].encode()).hexdigest() == rp["table_csv_sha256"]
```
The signed report holds hashes, offsets, verdicts, rule ids and receipt ids, never the copy. It embeds the signed
grounding report for the support verdicts. Each receipt id resolves at `GET https://api.decosa.ai/receipts/{id}`.

## Honest limits
- Text only: artwork, colours and label images are not read.
- It checks the Directive's text, not national transposing laws, and not the durability and repair bans (23d to 23j).
  The proposed Green Claims Directive is not law and is not checked.
- Verdicts come from a language model plus fixed rules. On our synthetic eval it flagged every planted violation in
  most runs, and borderline claims can change from run to run; see the numbers on the Stack tab. A person reviews every
  finding. Not legal advice.

Run it yourself (containers)

On request. The container images and the compose file aren’t public yet. Ask for self-host access and Decosa sends the registry (DECOSA_REGISTRY) and the compose file’s URL (DECOSA_COMPOSE_URL) these steps use. They are the steps we tested end to end on a fresh machine.

# Decosa green-claims substantiation check: run it yourself (containers)

You are setting up the Decosa green-claims check on this machine, so unreleased copy and supplier contracts never
leave it. It judges every environmental claim in marketing copy against Directive (EU) 2024/825 (or the UK CMA Green
Claims Code), grounds claims in the evidence file, and returns a CSV claim table and a signed report. Nothing is sent to
Decosa's hosted API.

Status: the container images (${DECOSA_REGISTRY}/decosa-*) and the compose file are on request while self-host is in early access (not on a public registry yet): ask at https://decosa.ai/contact?topic=self-host, and Decosa sends the registry as DECOSA_REGISTRY, the compose file URL as DECOSA_COMPOSE_URL, and pull access. If a pull fails with
"not found", "denied" or "unauthorized", stop and tell me. Do not substitute other images.

Ask me before any command that needs sudo, and show me the command first.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/green-claims-check.zip (3 KB, 10 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `docker compose exec api python scripts/rehearse.py green-claims-check` (the api image carries the same bundle under /app/rehearsal/green-claims-check/;
   with no key set, the script asks the local API for a short demo token). From a decosa-api checkout instead:
   `python scripts/rehearse.py green-claims-check --bundle green-claims-check.zip --base-url http://127.0.0.1:<PORT>`.
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "at least three claims are banned", "the offset-based climate-neutral claim is banned under Annex I point 4c", "the generic 'eco-friendly' claim is banned"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## Steps
1. Docker: if `docker compose version` fails, install Docker Engine and the compose plugin using Docker's official
   instructions for this distribution (docs.docker.com/engine/install). Install the NVIDIA container toolkit and check
   `docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi`.
2. Fetch the compose file:
   `mkdir -p ~/decosa && cd ~/decosa && curl -fsSL "${DECOSA_COMPOSE_URL}" -o compose.yaml`
   Read it. Keep the `llm` service (Qwen3.8-27B on vLLM, with prefix caching on) and the `api` service. For the `api`
   service set `DECOSA_LLM_ROUTE=direct`, `DECOSA_LLM_URL=http://llm:8000/v1`, `DECOSA_LLM_MODEL=qwen3.8-27b` and bind
   every port to 127.0.0.1. Never set the gateway route on this box: it would send the copy to the Decosa API.
3. Pull and start: `docker compose pull && docker compose up -d`. Wait for the `llm` health check (the first start
   downloads about 20 GB of weights).
4. Check: `curl -fsS http://127.0.0.1:<PORT>/green/info` lists the rule ids, their verbatim texts and the limits;
   `GET /attest/signing-key` shows this box's public key. Show me the key: it is what reviewers pin to verify my reports.
5. Smoke test: get a token with `POST /demo/session {"vertical":"green-claims-check"}`, fetch `GET /green/samples`, and
   send the `fernhollow-planted` sample (copy, brand, product, mode, evidence) to `POST /green/check`. Expect
   `status: "banned_claims"`, with bans under `eu-4a` (eco-friendly), `eu-4c` (climate neutral via a rainforest
   project) and `eu-2a` (the in-house seal), and the recycled-plastic claim `substantiated` with a quoted span. Then
   send `quillbrook-compliant`: expect no `banned` verdict. Then `POST /green/verify` with the report, report_md and
   table_csv: `valid_signature`, `signed_by_this_server`, `report_md_matches` and `table_csv_matches` must all be true.
6. Report back: the public key and key id, both statuses, the verdicts and how long each check took.

Off by default. Joining as a provider serves other people's requests on this GPU; never do it on a box that holds
unreleased copy or supplier contracts. If I ask for it later, follow the Provide page instead of improvising.

No NVIDIA GPU? This tool also runs entirely on an Apple Silicon Mac (MLX, 32 GB of unified memory or more): use https://decosa.ai/prompts/green-claims-check-mac.md instead.
Run it on your own hardwareWhat it needs, and the prompt that sets it up

Run it on your own GPU

Same app, same pinned models, your hardware. Nothing goes to our servers and there are no Decosa charges.

  • CPU only, 64 GB RAMDoesn't fit

    Qwen3.8-27B (NVFP4) needs a GPU.

  • GeForce RTX 4090standard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVFP4) with A community 4-bit build of Qwen3.8-27B (AWQ or GGUF). This build is NVIDIA NVFP4, which needs a Blackwell GPU. (Memory is an estimate.)

  • GeForce RTX 5090standard tierRuns

    The standard tier fits with changes: Qwen3.8-27B (NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.

  • 2x GeForce RTX 5090standard tierRuns

    The standard tier fits with changes: Split the language model across the GPUs with tensor parallelism (vLLM --tensor-parallel-size).

  • L40Sstandard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVFP4) with Qwen3.8-27B official FP8. This build is NVIDIA NVFP4, which needs a Blackwell GPU.

  • H100 80 GB (SXM)standard tierRuns

    The standard tier fits with changes: Replace Qwen3.8-27B (NVFP4) with Qwen3.8-27B official FP8. This build is NVIDIA NVFP4, which needs a Blackwell GPU.

  • RTX PRO 6000 Blackwell 96 GBstandard tierRuns

    The standard tier fits (57.6 of 96 GB).

  • 2x RTX PRO 6000 Blackwell 96 GBstandard tierRuns

    The standard tier fits (57.6 of 192 GB).

  • Apple M3 Ultra (Mac Studio), 96 GBstandard tierRuns

    The standard tier fits (32 of 96 GB).

  • Apple M5 Max, 64 GBstandard tierRuns

    The standard tier fits (32 of 64 GB).

Memory per component comes from measured footprints, the tool's stack.json, or an estimate from its parameter count, and each is labelled that way below. Only an RTX PRO 6000 and an M3 Ultra Mac Studio have actually been run.

On request. The container images and the compose file aren’t public yet. Ask for self-host access and Decosa sends the registry (DECOSA_REGISTRY) and the compose file’s URL (DECOSA_COMPOSE_URL) these steps use. They are the steps we tested end to end on a fresh machine.

  1. 1

    Check the GPU, Docker and the NVIDIA Container Toolkit

    The driver must see the GPU, and Docker must be able to pass it into a container.

    nvidia-smi
    docker compose version
    docker run --rm --gpus all ubuntu nvidia-smi
  2. 2

    Fetch the compose file

    One file describes the API and the language model as services.

    mkdir -p ~/decosa && cd ~/decosa
    curl -fsSL "${DECOSA_COMPOSE_URL}" -o compose.yaml
  3. 3

    Pull and start

    The first start downloads pinned model weights, tens of gigabytes.

    docker compose pull
    docker compose up -d
  4. 4

    Check health

    Wait until the API reports ok with the language model loaded. Then point your app at the local base URL.

    curl -fsS http://localhost:<PORT>/healthz
    # {"ok": true, "llm": true, ...}
    curl -fsS -X POST http://localhost:<PORT>/demo/session \
      -H 'Content-Type: application/json' -d '{"vertical":"green-claims-check"}'

Set up with a coding agent, rehearse on mock data, then go private

  1. Set up with a coding agent. Paste the self-host prompt into a coding agent on the machine that will run the service. We recommend Claude Code with Claude Opus 5.5; any capable coding agent works.
  2. Rehearse on mock data. The agent runs the tool on a bundle of synthetic inputs and checks each answer against the bundle's expected.json. Every check must print PASS.
  3. Go private. Only then do you run your own data against the local API, yourself, on that machine. Never give the agent real data during setup: a coding agent that runs in the cloud sees everything in its context, so keep real data out of the chat and out of the files it reads.
Rehearsal command
docker compose exec api python scripts/rehearse.py green-claims-check

Download the mock-data bundle (3 KB, 10 checks)expected.json

Product-page copy for a fictional laundry liquid with planted EU greenwashing violations (a generic eco claim, offset-based climate neutrality, an own-brand seal, a net-zero target with no plan) and an evidence file. At least three claims must come back banned, the offset claim under EU Annex I point 4c, a backed claim must be substantiated with a quoted evidence span, and the signed report must verify and catch a changed status.

What the rehearsal checks
  • at least three claims are banned
  • the offset-based climate-neutral claim is banned under Annex I point 4c
  • the generic 'eco-friendly' claim is banned
  • a claim the evidence backs is substantiated with a quoted evidence span
  • the delivery line is not treated as an environmental claim
  • the signed report verifies
  • the report matches the copy
  • the report matches its CSV claim table
  • a report with its status changed to clear no longer verifies
  • every model call has a signed receipt

Licence: Synthetic: the brand Fernhollow, its suppliers and every document in the evidence file are fictional, written for Decosa. Part of decosa-api, AGPL-3.0-or-later.

Prompt for your coding agent

# Decosa green-claims substantiation check: run it yourself (containers)

You are setting up the Decosa green-claims check on this machine, so unreleased copy and supplier contracts never
leave it. It judges every environmental claim in marketing copy against Directive (EU) 2024/825 (or the UK CMA Green
Claims Code), grounds claims in the evidence file, and returns a CSV claim table and a signed report. Nothing is sent to
Decosa's hosted API.

Status: the container images (${DECOSA_REGISTRY}/decosa-*) and the compose file are on request while self-host is in early access (not on a public registry yet): ask at https://decosa.ai/contact?topic=self-host, and Decosa sends the registry as DECOSA_REGISTRY, the compose file URL as DECOSA_COMPOSE_URL, and pull access. If a pull fails with
"not found", "denied" or "unauthorized", stop and tell me. Do not substitute other images.

Ask me before any command that needs sudo, and show me the command first.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/green-claims-check.zip (3 KB, 10 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `docker compose exec api python scripts/rehearse.py green-claims-check` (the api image carries the same bundle under /app/rehearsal/green-claims-check/;
   with no key set, the script asks the local API for a short demo token). From a decosa-api checkout instead:
   `python scripts/rehearse.py green-claims-check --bundle green-claims-check.zip --base-url http://127.0.0.1:<PORT>`.
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "at least three claims are banned", "the offset-based climate-neutral claim is banned under Annex I point 4c", "the generic 'eco-friendly' claim is banned"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## Steps
1. Docker: if `docker compose version` fails, install Docker Engine and the compose plugin using Docker's official
   instructions for this distribution (docs.docker.com/engine/install). Install the NVIDIA container toolkit and check
   `docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi`.
2. Fetch the compose file:
   `mkdir -p ~/decosa && cd ~/decosa && curl -fsSL "${DECOSA_COMPOSE_URL}" -o compose.yaml`
   Read it. Keep the `llm` service (Qwen3.8-27B on vLLM, with prefix caching on) and the `api` service. For the `api`
   service set `DECOSA_LLM_ROUTE=direct`, `DECOSA_LLM_URL=http://llm:8000/v1`, `DECOSA_LLM_MODEL=qwen3.8-27b` and bind
   every port to 127.0.0.1. Never set the gateway route on this box: it would send the copy to the Decosa API.
3. Pull and start: `docker compose pull && docker compose up -d`. Wait for the `llm` health check (the first start
   downloads about 20 GB of weights).
4. Check: `curl -fsS http://127.0.0.1:<PORT>/green/info` lists the rule ids, their verbatim texts and the limits;
   `GET /attest/signing-key` shows this box's public key. Show me the key: it is what reviewers pin to verify my reports.
5. Smoke test: get a token with `POST /demo/session {"vertical":"green-claims-check"}`, fetch `GET /green/samples`, and
   send the `fernhollow-planted` sample (copy, brand, product, mode, evidence) to `POST /green/check`. Expect
   `status: "banned_claims"`, with bans under `eu-4a` (eco-friendly), `eu-4c` (climate neutral via a rainforest
   project) and `eu-2a` (the in-house seal), and the recycled-plastic claim `substantiated` with a quoted span. Then
   send `quillbrook-compliant`: expect no `banned` verdict. Then `POST /green/verify` with the report, report_md and
   table_csv: `valid_signature`, `signed_by_this_server`, `report_md_matches` and `table_csv_matches` must all be true.
6. Report back: the public key and key id, both statuses, the verdicts and how long each check took.

Off by default. Joining as a provider serves other people's requests on this GPU; never do it on a box that holds
unreleased copy or supplier contracts. If I ask for it later, follow the Provide page instead of improvising.

No NVIDIA GPU? This tool also runs entirely on an Apple Silicon Mac (MLX, 32 GB of unified memory or more): use https://decosa.ai/prompts/green-claims-check-mac.md instead.

Help me customise for my hardware

Pick your GPU or Mac, or enter its memory. You get the tier that fits, the model swaps it needs, measured speed where we have it, and a setup prompt with those choices written in.

Hardware

GeForce RTX 5090: 32 GB GDDR7, 1,792 GB/s, FP8 and NVFP4. NVIDIA product page

RunsGreen-claims substantiation check on GeForce RTX 5090: use the Standard · one GPU for the model (hosted demo) tier

The standard tier fits with changes: Qwen3.8-27B (NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.

What this tool's stack says about this hardware:

  • 1x RTX 5090 32 GB (fits): Estimate: Qwen3.8-27B NVFP4 needs about 20 GB of weights plus KV cache; not run for this use case.

Standard · one GPU for the model (hosted demo): what changesuses estimates

  • Qwen3.8-27B (NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.
Memory per component
  • Rulepack, sentences, evidence spans, verdicts...: decosa-api green module (decosa_api/verticals/green) on the promo pre-check engine, with the grounding module (decosa_api/verticals/grounding). CPU. Runs on CPU (vram_gb 0 in stack.json).
  • Claim typing, grounding judge, evidence reade...: Qwen3.8-27B (NVFP4). ~57.6 GB (at least ~28 GB), weights 21.4 GB (from stack.json). Qwen3.8-27B NVFP4: Weights 19.9 GiB (21.4 GB), measured (field stack.json). The compose file gives the server 0.60 of a 96 GB card (57.6 GB) so the rest is FP8 KV cache for several sessions. The 28 GB minimum is an estimate: weights plus a short-context KV cache, which is why several stacks list a 32 GB RTX 5090 as 'estimate'. (stack.json lists 20 GB for this component.)

Expected speed

Not measured.

Not measured on this hardware. The only measured setups are an RTX PRO 6000 Blackwell and a Mac Studio M3 Ultra.

Setup prompt for this hardware

The self-host prompt for Green-claims substantiation check, with a hardware plan for GeForce RTX 5090 added after Step 0. Loading the full prompt; until then it points your agent at the prompt's URL.

# Set up Green-claims substantiation check on my hardware

Fetch https://decosa.ai/prompts/green-claims-check-selfhost.md and follow it (including Step 0: rehearse on mock data first), with the hardware plan below applied.

## Hardware plan for this machine (from https://decosa.ai/self-host/hardware?use=green-claims-check)

Target machine: GeForce RTX 5090 (32 GB of GPU memory; CUDA, FP8 and NVFP4).
Quality tier: Standard · one GPU for the model (hosted demo) (standard). Fit check: runs with changes, about 28 GB of 32 GB used; some memory numbers are estimates, not measurements.

First, check the machine: run `nvidia-smi` (or `rocm-smi`, or `sysctl hw.memsize` on a Mac) and confirm the GPUs and free memory match the line above. If they do not, stop and tell me before pulling anything.

Use these components (the setup below describes the standard tier; change it to match):
- Rulepack, sentences, evidence spans, verdicts...: decosa-api green module (decosa_api/verticals/green) on the promo pre-check engine, with the grounding module (decosa_api/verticals/grounding), CPU
- Claim typing, grounding judge, evidence reade...: Qwen3.8-27B (NVFP4) (nvidia/Qwen3.8-27B-NVFP4), 57.6 GB. Change: Qwen3.8-27B (NVFP4): run it at its smallest setting (about 28 GB instead of 57.6 GB), with a shorter context and fewer parallel sessions.

GPU placement (set each service's device and its vLLM --gpu-memory-utilization to about the share shown):
- GPU 0: Qwen3.8-27B (NVFP4) ~28 GB (88%); about 4 GB left

During the rehearsal, watch GPU memory. If a model fails to load or runs out of memory, lower its --max-model-len and --max-num-seqs first, then its memory share, and tell me what you changed.

The stack's own component list and compose layout: https://decosa.ai/prompts/green-claims-check-assemble.md

Or on a Mac Studio

No NVIDIA GPU needed: every model this tool uses runs natively on Apple Silicon through MLX. Any M-series Mac with 32 GB of unified memory or more. Measured speeds and what runs where

From a checkout of decosa-api, one command sets up the models and the API: scripts/mac/setup.sh

Mac prompt for your coding agent

# Decosa Green-claims substantiation check: run it on this Mac (Apple Silicon, no NVIDIA GPU)

You are setting up the Decosa Green-claims substantiation check on this Mac, natively on Apple Silicon. The models run on the Mac's GPU
through MLX and decosa-api runs from a git checkout with `uv`. Docker is not used for the models, because Docker on
macOS cannot reach the GPU. Nothing is sent to Decosa's hosted API.

Every model this tool needs runs on the Mac. It needs 32 GB of unified memory or more.

Ask me before any command that needs sudo or installs software with Homebrew, and show me the command first. Never stop
or kill a process this setup did not start; if a port is taken, pick another one.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/green-claims-check.zip (3 KB, 10 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `.venv/bin/python scripts/rehearse.py green-claims-check` in the decosa-api checkout (the key comes from ~/.decosa-mac/api.key).
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "at least three claims are banned", "the offset-based climate-neutral claim is banned under Annex I point 4c", "the generic 'eco-friendly' claim is banned"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## What runs where

| Part | On an NVIDIA GPU | On this Mac | Status |
|---|---|---|---|
| Rulepack, sentences, evidence spans, verdicts, claim table and signed report (no model; CPU) | Python on CPU | The same Python module, run with uv | Runs, measured |
| Claim typing, grounding judge, evidence reader and rewrite | NVFP4 on vLLM 0.29 (Blackwell) | MLX 4-bit (EigenLabs/Qwen3.8-27B-4bit) on mlx_lm.server 0.31.3; oMLX 0.6.1 with MTP as an option | Runs, measured |

## Steps
1. Check the machine: `uname -m` must print `arm64` (an M-series chip; Intel Macs cannot run MLX), and
   `sysctl -n hw.memsize` should be at least 32 GB for this tool. Check about 30 GB of free disk with
   `df -h ~`. Show me the chip (`sysctl -n machdep.cpu.brand_string`) and the memory.
2. Tools: `uv --version`. If it is missing, ask me, then `brew install uv`.
3. Code: `git clone <decosa-api source: on request at https://decosa.ai/contact?topic=self-host> ~/decosa-api` (access required) and `cd ~/decosa-api`.
   Check that `scripts/mac/setup.sh` exists; if it does not, the checkout is too old: stop and tell me.
4. Start everything with one command: `scripts/mac/setup.sh`. It creates `.venv` (decosa-api)
   and `.venv-mac` (MLX, mlx-lm, mlx-audio), downloads the weights with the Hugging Face CLI (about 16 GB for the
   language model), starts the model servers and decosa-api on 127.0.0.1, and mints a local API key
   into `~/.decosa-mac/api.key` (mode 0600). The first run takes a while because of the downloads; later runs reuse them.
   If a download fails with 401 or 403, ask me for a Hugging Face token and set `HF_TOKEN`.
5. Check health: `scripts/mac/setup.sh status` shows each server, and `curl -fsS http://127.0.0.1:8445/healthz` must
   report `"llm": true`. `curl -fsS http://127.0.0.1:8445/attest/signing-key` shows this Mac's public key:
   show it to me, because it is what others pin to check the receipts and records this Mac signs.
6. Smoke test: `.venv/bin/python scripts/mac/bench_usecases.py green-claims-check`. It runs the tool's own sample end to end
   against the local API with the local key and prints `ok`, the wall time, the model calls and the receipts.
   `ok=True` is the pass condition. If it fails, read `~/.decosa-mac/logs/*.log` and tell me what you found.
7. Point the app at it: the API is `http://127.0.0.1:8445` with `Authorization: Bearer $(cat ~/.decosa-mac/api.key)`,
   the same routes as the hosted API. To stop everything: `scripts/mac/setup.sh stop`.
8. Report back: the chip and memory, the public key, the smoke-test result and its time, and the output of
   `scripts/mac/setup.sh status`.

## Good to know
- Receipts: every model call is signed with this Mac's own Ed25519 key and names the exact MLX weights
  (`qwen3.8-27b-mlx-4bit` with a hash of the downloaded files). There is no gateway countersignature on a
  self-hosted Mac.
- The weights are a 4-bit MLX build of the same open models, not the NVFP4 build the hosted route and the published
  evals use. Expect small differences in wording and scores.
- Faster drafting: `scripts/mac/setup.sh stop && scripts/mac/setup.sh --engine omlx` serves the
  model with oMLX and multi-token prediction (about 2x faster for a single long answer, no faster for many parallel
  calls; typed judgments then use sampling because oMLX returns no log-probabilities).
- Built from the same parts as the measured tools; merged after the Mac run, so not run on the Mac yet.
- Measured speeds for a Mac Studio M3 Ultra and the memory each tool needs: https://decosa.ai/mac. Full details:
  `docs/self-host-mac.md` in the checkout.

The proof

How we tested itEval results and end-to-end checks, hosted and self-hosted, with dates

Verified end to end

Hosted: verified 25 Sep 2026 · measured 25 Sep 2026: · p50 8.6 s · ~$0.013 per run · 26 receipts

Loading the nightly status…

Self-host: verified 25 Sep 2026 · fresh clone, compose up, sample against local model servers

Measured cost to run: about $0.80 per 100 pieces (hosted, 25 Sep 2026). Self-hosting is free: the code is open and the models are open-weight. You pay only for your own hardware and power.

A fresh clone of a decosa-api pre-release build (not yet merged to main), the api image built from it, the compose file from this prompt, then its smoke steps against the already-running local Qwen3.8-27B vLLM on the direct route. All three samples ran (4.5-6 s each): Fernhollow banned_claims with 5 bans, Quillbrook nothing_flagged, Northwick (UK) high_risk; the report verified and a changed status failed. Model-server startup itself not re-verified.

Known limits (3)
  • Text only: artwork, colours and label images are not read. Describe a label in words to have it checked.
  • Checks the Directive's text, not national transposing laws, and not the durability and repair bans (23d to 23j).
  • The eval is small and synthetic, and the gateway is not fully deterministic: the same piece can get a different verdict on a borderline claim from run to run. A person reviews every finding.

Eval results, nightly checks and cost per runVerify a run

How it's builtThe steps, the models and what each one checks
Hosted · by Decosa

Get an API key

  • Call the green-claims substantiation check API from your own code in minutes.
  • Every model answer carries a signed receipt.
  • Nothing to install; we run the models.
Self-host · your GPUs

Run it yourself, on request

  • The same open models and app, on 1× RTX PRO 6000 (96 GB) or 1× RTX 5090 (32 GB) for the model; the rulepack, grounding spans and the report run on CPU.
  • Data never leaves your machines, and there are no Decosa charges.
  • One prompt for Claude Code or Codex assembles the whole stack.
  • Early access: the container images are not public yet and the source needs access; the prompt says how to ask.
The open stack

Every environmental claim in your copy judged against the EU bans that apply from 27 September 2026, with the rule cited, the evidence line that backs it, and a rewrite.

Send pack copy, a product page or an ad script, plus the evidence file behind it: LCA summaries, certificates, offset contracts, plans. Each sentence is typed by one receipted call (generic term, climate neutrality, offsets, a label, a future target, a whole-product claim, a legal requirement sold as a feature). Environmental claims are then grounded in the evidence file by the grounding module, which cites the span, and one more call reads the evidence for offsets, recognised ecolabels, certification schemes, implementation plans and whole-or-part coverage. A deterministic rulepack gives each claim a verdict (banned, needs substantiation, substantiated, or not an environmental claim) with the rule cited, and the model drafts a rewrite that says only what the evidence backs. You get a CSV claim table, a Markdown report and a signed record. EU mode follows Directive (EU) 2024/825; UK mode follows the CMA Green Claims Code. It is a triage for a compliance reviewer, never a compliance sign-off.

Deployment
Hosted or self-host
Regulatory
Checked 25 Sep 2026 against the primary sources. EU: Directive (EU) 2024/825 (OJ L, 6.3.2024; EUR-Lex link under Tools) amends the Unfair Commercial Practices Directive 2005/29/EC. Member States had to adopt their measures by 27 March 2026 and apply them from 27 September 2026 (Article 4(1)); national transposing laws are what apply, and this tool does not check national differences. It encodes the new Annex I bans (2a sustainability labels without a certification scheme or public authority, 4a generic claims without recognised excellent environmental performance, 4b whole-product or whole-business claims when only a part qualifies, 4c offset-based neutral, reduced or positive greenhouse-gas claims, 10a legal requirements presented as a distinctive feature) and Article 6(2)(d) (future performance claims without a verified implementation plan), which is case by case, so it can only raise 'needs substantiation'. The durability, repair and software bans (23d to 23j) are not checked. The proposed Green Claims Directive (2023/0085(COD)) is not law and is not encoded: on 20 June 2025 the Commission announced its intent to withdraw it and the last trilogue was cancelled; the 2026 work programme lists it as pending (European Parliament Legislative Train, updated 1 Aug 2026). UK: the CMA Green Claims Code (20 Sep 2021; GOV.UK link under Tools) is guidance, not a list of per se bans, so UK mode never says 'banned'; since April 2025 the CMA can itself fine up to 10% of global turnover for consumer-law breaches under the DMCC Act 2024 (CMA press release, 7 Apr 2025). Text only: artwork, colours and label images are not read. Verdicts come from a language model plus fixed rules and can be wrong in both directions (see the eval). Not legal advice, and a clean result is not a compliance sign-off. The hosted demo keeps nothing; unreleased copy and supplier contracts belong on a self-hosted box. Model licence: Apache-2.0 (Qwen3.8-27B).
Architecture
Text description

Marketing copy (pack, web page or ad script) and the brand's evidence file (LCA summaries, certificates, offset contracts, plans) go to the green-claims check. It splits the copy into sentences and numbers the evidence spans. Qwen3.8-27B makes one call per sentence to type it, and for each environmental claim a grounding call that cites the evidence span and an evidence call that reads offsets, ecolabels, schemes, plans and coverage and drafts a rewrite. A deterministic rulepack (Directive (EU) 2024/825 Annex I and Article 6(2)(d), or the CMA Green Claims Code) turns those into a verdict with the rule cited. Outputs: a CSV claim table, a Markdown report and a signed JSON record. On the hosted route every model call gets a signed receipt that our gateway countersigns. In self-host mode everything runs on your machine.

Architecture

At a glance

Data retention
Nothing stored: copy and evidence live in memory for the request. The signed report holds hashes, offsets, verdicts, rule ids and receipt ids, never the copy.
What leaves the box
Hosted: every model call goes through our gateway to the GPU serving Qwen3.8-27B, and its receipt (hashes, token counts, no text) is kept by the gateway and this API. Self-hosted on the direct route: nothing leaves the box.
Input formats
Text only: copy up to 8,000 characters and 40 claim sentences; up to 10 evidence files (LCA, certificate, offset contract, plan, policy, other) and 200,000 characters. Extract PDF text yourself. Evidence is optional, but without it nothing can be substantiated.
What it will not say
Never 'compliant'. A clean result reads 'nothing flagged (not a compliance sign-off)'. UK mode never says 'banned', because the CMA code is guidance.
Typical run
The Fernhollow sample: a few dozen model calls and about a cent at the gateway list price; the eval average per piece is lower. Each run shows its own measured cost.
Quality tiers

Pick the tier for the quality you need

Same app at every tier. What changes is the models, the hardware they need, and whether receipts are signed. Scores are measured with the source named, or marked not measured.

  • In the hosted demo

    Standard

    one GPU for the model (hosted demo)

    Qwen3.8-27B types each sentence, judges support against the evidence and reads the evidence file, each in its own receipted call; the rulepack decides the verdict. This is what the hosted API runs.

    Models
    • decosa-api green module (decosa_api/verticals/green) on the promo pre-check engine, with the grounding module (decosa_api/verticals/grounding)
    • Qwen3.8-27B (NVFP4)
    Hardware
    1x RTX PRO 6000 96 GB (measured) or 1x RTX 5090 32 GB (estimate)
    Quality evidence
    • Held-out test2 (6 synthetic pieces, 44 sentences): verdicts right, first run / three reruns43/44 / 41/44 eachdocs/evals/green-claims-check.md (v2 and v2.2 result files), 25 Sep 2026
    • Planted violations flagged, held out (test2 / v1 on test)19/19 (18/19 in reruns) / 30/30docs/evals/green-claims-check.md
    • False alarms on clean claims and non-claims, held out (test2 / v1 on test)0/25 (1/25 in reruns) / 5/39docs/evals/green-claims-check.md
    • Substantiated claims whose cited span holds the expected evidence (test2)16/16docs/evals/green-claims-check.md
    • Per rule on test2 (2a, 4a, 4b, 4c, 10a, 6(2)(d)), first runprecision and recall 1.00 each, on 3, 4, 2, 4, 3 and 2 planted claims; reruns: 10a recall 0.67, 2a precision 0.69docs/evals/green-claims-check.md
    • Word list alone (no model), test212/44 verdicts, 4/19 violations flaggeddocs/evals/green-claims-check/baseline-test2-eu.json
    Latency
    measured: seconds per short piece through the shared gateway (longer under load); faster self-hosted on the direct route.
    Verification
    Proof: strongEvery model call is a separate gateway call with a gateway-signed receipt; the signed report lists them all.

Also runs on

  • Pack artwork and other languagesQwen3.8-27B vision inputnot builtRead claims in pack artwork, badges and colours from images with the 27B's own vision input, and check copy in other EU languages. Not built. Hardware: 1x RTX PRO 6000 96 GB (estimate).

We host these ourselves when needed: small models get more of our own compute unless we detect a shortage, so they need no community providers.

Components

Every model in the stack

Models in this stack. Each row has a button that shows its licence, engine, verification and evidence.
ModelDetails
Rulepack, sentences, evidence spans, verdicts, claim table and signed report (no model; CPU)decosa-api green module (decosa_api/verticals/green) on the promo pre-check engine, with the grounding module (decosa_api/verticals/grounding)
0 GBProof: partial
Claim typing, grounding judge, evidence reader and rewriteQwen3.8-27B (NVFP4)nvidia/Qwen3.8-27B-NVFP4 on Hugging Face (opens in a new tab)
27.8B · 20 GBProof: strongIn the hosted demo
Pack artwork and label reader (alternate)Qwen3.8-27B vision inputnvidia/Qwen3.8-27B-NVFP4 on Hugging Face (opens in a new tab)
27.8B · 20 GBNo proof yetSelf-host only

Around the models

Tools, services and hardware

Tools

Services

  • decosa-api:8445
    ${DECOSA_REGISTRY}/decosa-api:<tag>

    GET /green/info, /green/samples; POST /green/check (SSE or JSON), /green/verify. Keeps no text.

  • vLLM (model):8114
    vllm/vllm-openai@sha256:c2914767605584b6d8f45686b82de173ecc99e781897aa3d0a66dacd72c51ae1

    Qwen3.8-27B NVFP4 behind our gateway (hosted) or called directly (self-host).

Hardware

  • 1x RTX PRO 6000 Blackwell 96 GB Fits

    Measured on our server: the hosted demo, the eval and the self-host check ran on this card, shared with other services.

  • 1x RTX 5090 32 GB Fits

    Estimate: Qwen3.8-27B NVFP4 needs about 20 GB of weights plus KV cache; not run for this tool.

Latency per lane

  • one piece of 7-10 sentences, hosted gateway route8.6 s

    Measuredmeasured on our server 2026-09-25: median of 7 runs of the three samples through POST /green/check (6-38 s; the slow runs were under shared load)

  • one piece, self-host direct route5.5 s

    Measuredmeasured on our server 2026-09-25: 4.5-6 s per sample in the fresh-clone self-host check

  • model calls per piecen/a

    Measuredmeasured 2026-09-25: about 19 calls, 1.6k generated and 18k prompt tokens per piece (test2 eval)

Notes

  • Held out: on 6 synthetic pieces (44 sentences) written after the prompts were frozen, the first run got 43 of 44 verdicts right, flagged 19 of 19 planted violations, raised no false alarms and quoted the right evidence for all 16 substantiated claims. Three reruns an hour later gave 41 of 44 each (the gateway is not fully deterministic): one 10a claim missed and one clean claim flagged.
  • The pieces are short, synthetic and written by the same agent that wrote the prompts; 2 to 4 planted violations per rule. Treat the numbers as a check that the rules work, not as accuracy on real copy.
  • Annex I 10a (a legal requirement sold as a feature) depends on the model knowing the law covers the whole product category. A word list covers CFCs, RoHS and phosphates in laundry and dishwasher detergents; other cases are up to the model and were missed in some runs.
  • 'Substantiated' needs the grounding judge to say the evidence supports the claim and to cite the span. It is strict: a fair paraphrase is sometimes called partial, which turns a clean claim into 'needs substantiation'. That is the safe direction.
  • Suggested rewrites are drafted by the model. A draft that still uses a generic or neutrality term (it kept 'carbon neutral' in 2 to 3 of about 10 held-out drafts) is withheld and the report says to rewrite that claim by hand.
  • The signed report holds hashes, offsets, verdicts, rule ids and receipt ids; the CSV table and the Markdown report quote the copy and are returned to you, with their hashes in the signature.
Assemble it

Run this exact stack on your machine

Paste into Claude Code / Codex to assemble this stack locally. The prompt checks your GPU, pulls the pinned models, writes the compose file and runs a smoke test.

green-claims-check/assemble-prompt.md137 lines
# Assemble the Decosa green-claims substantiation check on this machine

You are setting up a check for environmental claims in marketing copy (pack text, product pages, ad scripts). It takes
the copy and the evidence file behind it (LCA summaries, certificates, offset contracts, plans, policies), judges every
environmental claim against Directive (EU) 2024/825 (or, in UK mode, the CMA Green Claims Code), grounds the claims it
can in a quoted span of the evidence, drafts rewrites, and returns a CSV claim table, a Markdown report and a JSON
record signed by this box's own key. Work step by step, show me each command before you run anything with `sudo`, and
stop to ask if a check fails.

## Step 0: set up with a coding agent, rehearse on mock data, then go private

This prompt is for a coding agent running on the machine that will host the service. We recommend Claude Code with
Claude Opus 5.5; any capable coding agent works. Work in this order:

1. Set up on mock data only. During the whole setup you (the agent) work with the synthetic sample bundle below and
   nothing else. Do not ask me for real data, and do not open, read, list or copy files that hold real data, even to
   "test with something realistic".
2. Rehearse. When the steps below are done and the service is healthy, fetch the mock-data bundle for this tool,
   https://decosa.ai/samples/green-claims-check.zip (3 KB, 10 checks, synthetic or openly licensed: see `licence` in expected.json),
   show me what is in it, and run the rehearsal against the local API:
   `docker compose exec api python scripts/rehearse.py green-claims-check` (the api image carries the same bundle under /app/rehearsal/green-claims-check/;
   with no key set, the script asks the local API for a short demo token). From a decosa-api checkout instead:
   `python scripts/rehearse.py green-claims-check --bundle green-claims-check.zip --base-url http://127.0.0.1:<PORT>`.
   It sends the mock inputs to the local API and prints PASS or FAIL for each expected property (for example: "at least three claims are banned", "the offset-based climate-neutral claim is banned under Annex I point 4c", "the generic 'eco-friendly' claim is banned"). Show me
   the full output. Every check must pass. If one fails, fix the install and run it again; never edit `expected.json`
   to make a check pass.
3. Stop there. Once the rehearsal passes, tell me, and I will run my own data against the local API myself, on this
   machine.

For the person running this: a coding agent that runs in the cloud sees everything in its context, including files it
reads, command output and anything pasted into the chat. Keep real data out of the chat and out of anything the agent
can read. Switch to your own data only after the rehearsal has passed and the agent's work is done.

## 0. Ground rules and licences
- Model: Qwen3.8-27B (Apache-2.0), used for three jobs: typing each sentence (generic term, climate neutrality,
  offsets, label, future target, whole product, legal requirement), the grounding judge (is the claim in the evidence,
  with the span), and reading the evidence (offsets, ecolabels, certification schemes, plans, coverage) with a rewrite.
  The check itself is decosa-api (AGPL-3.0-or-later) and needs no GPU of its own.
- Copy and evidence stay on this machine. Bind every port to 127.0.0.1. The service keeps no text: nothing is written to
  disk and logs carry counts only. Keep it that way; do not add request logging.
- Be honest about what it is: a triage for a compliance reviewer, not legal advice and never a compliance sign-off. It
  reads text only (not artwork or colours), checks the Directive's text (not national transposing laws), and its
  findings come from a language model that can be wrong both ways.

## 1. Check the machine
1. `nvidia-smi`: one GPU with at least 32 GB (Qwen3.8-27B NVFP4 needs about 20 GB of weights plus KV cache; an RTX PRO
   6000 96 GB is what we measured on, an RTX 5090 32 GB should fit but we have not run this tool on one). Driver
   570 or newer. Blackwell cards run NVFP4; on older cards use `Qwen/Qwen3.8-27B-FP8`.
2. `docker --version` and `docker compose version`. If Docker or the NVIDIA container toolkit is missing, install them
   from the official Docker and NVIDIA repositories after asking me, then run
   `docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi`.
3. Disk: about 30 GB free.

## 2. Images and weights
- `${DECOSA_REGISTRY}/decosa-api:<tag>` (**publishing soon**). If the pull fails, build from source:
  `git clone <decosa-api source: on request at https://decosa.ai/contact?topic=self-host>` (access required), check out the newest release tag that
  contains `decosa_api/verticals/green/` and `decosa_api/verticals/grounding/` (`main` until one does), and build
  `docker/api/Dockerfile`.
- `vllm/vllm-openai:v0.29.0` for the model; weights `nvidia/Qwen3.8-27B-NVFP4` (revision
  `482ca0f3832238542f8f5295dde86b5f22711d80`), or `Qwen/Qwen3.8-27B-FP8` on a card without NVFP4.

## 3. docker-compose.yml
Write this in `~/decosa/green/`:

```yaml
services:
  llm:
    image: vllm/vllm-openai:v0.29.0
    command: ["--model", "nvidia/Qwen3.8-27B-NVFP4", "--served-model-name", "qwen3.8-27b", "--max-model-len", "32768",
              "--enable-prefix-caching"]
    ports: ["127.0.0.1:8114:8000"]
    volumes: ["~/.cache/huggingface:/root/.cache/huggingface"]
    deploy: { resources: { reservations: { devices: [{ driver: nvidia, count: 1, capabilities: [gpu] }] } } }
    healthcheck: { test: ["CMD", "curl", "-fs", "http://localhost:8000/v1/models"], interval: 30s, retries: 20 }
  api:
    image: ${DECOSA_REGISTRY}/decosa-api:<tag>
    ports: ["127.0.0.1:8445:8445"]
    environment:
      DECOSA_HOST: 0.0.0.0
      DECOSA_PORT: "8445"
      DECOSA_DATA_DIR: /data
      DECOSA_LLM_ROUTE: direct
      DECOSA_LLM_URL: http://llm:8000/v1
      DECOSA_LLM_MODEL: qwen3.8-27b
      DECOSA_GREEN_MAX_CONCURRENT: "3"
      DECOSA_GREEN_WORKERS: "6"
      DECOSA_BUDGET_LLM_TOKENS: "60000"
    volumes: ["decosa-data:/data"]
    depends_on: { llm: { condition: service_healthy } }
    healthcheck: { test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8445/green/info', timeout=4)"], interval: 30s, retries: 10 }
volumes:
  decosa-data:
```

The api keeps its state (keys, receipts, this box's signing key) in the named volume `decosa-data`, not in a host
folder: the image runs as an unprivileged user (uid 10001), and a host folder that Docker creates is owned by root,
which stops the api with `PermissionError: [Errno 13] Permission denied: '/data/keys.sqlite'`. Then start everything:
`docker compose up -d`.

Prefix caching matters: every environmental claim of one check sends the same evidence file first, so the server
reuses it. Evidence files above 24,000 characters in total are narrowed per sentence with BM25 instead.

On the first start the api service creates this box's Ed25519 key in the `decosa-data` volume (`/data/attest/` in the
api container, mode 0600). Back it up with `docker compose cp api:/data/attest ./attest-backup` and keep that copy
private. Never print it. Every model call on the direct route gets a receipt signed with that key (status `attested`):
an attestation by me, the operator, not a proof of computation. Never set `DECOSA_LLM_ROUTE=gateway` on this box: the
gateway route sends the copy to the Decosa API.

## 4. Smoke test
1. `curl -s localhost:8445/green/info | jq '{rules: (.rules | keys), modes: (.modes | keys)}'` lists the rule ids
   (`eu-2a`, `eu-4a`, `eu-4b`, `eu-4c`, `eu-10a`, `eu-6-2-d`, `eu-6-1`, and the `uk-*` ones).
2. Token: `T=$(curl -s -XPOST localhost:8445/demo/session -H 'content-type: application/json' -d '{"vertical":"green-claims-check"}' | jq -r .token)`.
3. `curl -s localhost:8445/green/samples > samples.json`, then
   `jq '.[0] | {copy, brand, product, mode, evidence}' samples.json > planted.json` and
   `curl -s -XPOST localhost:8445/green/check -H "authorization: Bearer $T" -H 'content-type: application/json' -d @planted.json > res.json`.
   Expect `status: "banned_claims"`: "eco-friendly way to wash" banned under `eu-4a`, the rainforest "climate neutral"
   claim under `eu-4c`, the Green Promise seal under `eu-2a`, "phosphate-free, unlike ordinary detergents" under
   `eu-10a`, the whole-range claim under `eu-4b`, the 2040 net-zero target as `needs_substantiation` (`eu-6-2-d`), and
   "made from 50% post-consumer recycled plastic" `substantiated` with the supplier declaration quoted.
4. Do the same with `.[1]` (Quillbrook, written to comply): expect no `banned` verdict. `.[2]` is the UK sample: expect
   `high_risk`, never `banned`.
5. `jq '{report, report_md, table_csv}' res.json | curl -s -XPOST localhost:8445/green/verify -H 'content-type: application/json' -d @-`
   must show `valid_signature`, `signed_by_this_server`, `report_md_matches` and `table_csv_matches` true. Change the
   status in the report and verify again: it must fail.
6. Stream one with `-H 'accept: text/event-stream' -N`: `ready`, then `receipt` and `claim` events, then `report`,
   `budget` and `done`.
7. Time it. On our RTX PRO 6000, shared with other work, each sample took 4.5-6 s on the direct route on 25 Sep 2026.
   Tell me what you measure. Verdicts on borderline claims can change from run to run; that is expected.

## 5. Point the app at the local API
Set `NEXT_PUBLIC_DECOSA_API=http://127.0.0.1:8445` in the site's `.env.local`, or call `POST /green/check` from the
tool your team uses to route copy to review, and attach `table_csv`, `report_md` and the signed report to the review
job. Contract: `API_CONTRACT.md`, section "Green-claims substantiation check".

Off by default. Joining serves other people's requests on this GPU; never do it on a box that holds unreleased copy or
supplier contracts. If I ask for it, follow the provider guide at `/provide` on the site, and do not enable it without
my explicit yes.
Rules and regulations it checks againstDated, linked to the primary source; not legal advice

Regulation watch

Loading the watch status…

6 laws, rules and guidance pages cited; 5 watched nightly at the primary source. A change marks this page for a human re-check; nothing is edited automatically. What we cite and how it is watched

Technical detailsModels, where it runs, labels

In short

Last reviewed

What it is
A green claims checker for marketing copy: each environmental claim is judged against the EU bans that apply from 27 September 2026 (Directive (EU) 2024/825) or the UK CMA Green Claims Code, with the rule cited, the evidence line that backs it, and a rewrite that says only what the evidence supports. A triage for a reviewer, not a sign-off.
Who it's for
Teams in compliance and trust.
Where it runs
Hosted for published or synthetic copy; self-host for unreleased copy and supplier contracts
Key numbers

On 6 held-out synthetic pieces (44 sentences) the first run got 43 of 44 verdicts right and flagged 19 of 19 planted violations with no false alarms; later reruns gave 41 of 44. The pieces are small, and the same author wrote them and the prompts.

  • 43/44 (98%) Verdict accuracy, v2 on test2 (held out, first run) (held out, n = 44)
  • 19/19 Planted violations flagged, v2 on test2 (held out) (held out, n = 19)
  • 0/25 False alarms on clean claims and non-claims, v2 on test2 (held out) (held out, n = 25)
  • 8.6 s Median end-to-end run, hosted (QA sweep 2026-09-25)
All results, datasets and caveats
Models
Qwen3.8-27B
Where
Hosted for published or synthetic copy; self-host for unreleased copy and supplier contracts
Checks
Receipt per model call; signed report
Output
Structured data · Signed record or verdict
Data
Confidential business data
Hardware
1× 96 GB GPU
Licence
Permissive (Apache-2.0, MIT)

Questions people ask

What does the green claims checker flag?

Generic claims (Annex I 4a), whole-product claims when only a part qualifies (4b), offset-based neutral claims (4c), labels without a certification scheme (2a), legal requirements sold as features (10a), and future targets without a plan (Article 6(2)(d), which can only be 'needs substantiation'). The durability and repair bans (23d to 23j) are not checked.

Is 'climate neutral' banned in the EU from 27 September 2026?

When it rests on offsets, yes: Annex I 4c of Directive (EU) 2024/825 bans claims that a product has a neutral, reduced or positive greenhouse-gas impact based on offsetting, from 27 September 2026. The checker reads the evidence file for offsets, and a claim that rests on them is marked banned with 4c cited. National transposing laws are what apply. Not legal advice.

What is the current status of the Green Claims Directive?

It is not law. On 20 June 2025 the Commission announced its intent to withdraw the proposal and the last trilogue was cancelled; the European Parliament's Legislative Train (updated 1 Aug 2026) lists it as pending. It is not encoded here: EU mode follows Directive (EU) 2024/825, which Member States apply from 27 September 2026. Not legal advice.

How accurate is it?

On 6 held-out synthetic pieces (44 sentences) the first run got 43 of 44 verdicts right and flagged 19 of 19 planted violations with no false alarms; reruns gave 41 of 44. The pieces are small and written by the same agent as the prompts, and a word list alone got 12 of 44.

Will it tell me my copy is compliant?

Never. A clean result reads 'nothing flagged (not a compliance sign-off)', and UK mode never says 'banned' because the CMA Green Claims Code is guidance. A person reviews every finding.

Does it read pack artwork?

No. It reads text only; artwork, colours and label images are not read. Describe a label in words to have it checked.

Does it check national transposing laws?

No. It checks the Directive's text; the national laws transposing it are what apply, and national differences are not checked.

Ask a question or leave feedbackWe read every message and publish useful answers
Questions & feedback

Ask about Green-claims substantiation check

We read every message. Questions, comments and our answers show here once we have reviewed and approved them.

Loading questions…

This is a

Plain text. Please leave out personal, patient or client data.

Shown with your message if we publish it. Leave blank to post as “A visitor”.

Nothing appears here until we have read and approved it.