> ## Documentation Index
> Fetch the complete documentation index at: https://docs.veristar.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Live proof of adoption

> How the platform demonstrates live adoption by real SCF-awarded projects, and the evidence it collects.

How the platform proves the RFP's last deliverable: "at least three real SCF-awarded projects
instrumented for web analytics and one project instrumented for API traffic, with both the live
global operator view and a tenant-perspective screen-capture video demonstrating the experience"
(RFP section 5; plan phase 20). This page is the procedure and the format of the evidence. The
evidence itself is added to this directory only when it exists.

**Status on 2026-11-13: no evidence exists.** Production does not exist yet
([../deploy/production-readiness.md](https://docs.veristar.app/deploy/production-readiness.md)), and no project has been
asked to take part (input I11 needs human outreach). Nothing in this directory may be written
before the data it describes is real: no example project names, no sample screenshots, no
evidence file from a test or local stack.

## 1. What counts

| Requirement | Counts when |
| - | - |
| Three web projects | three different projects, each with an SCF award, each enrolled in production with at least one active site, each showing accepted, proof-checked page views on at least **14 consecutive UTC days** |
| One API project | one project with an SCF award (it may also be one of the three), sending its real HTTP server traffic through the second exporter, with request volume, status codes, p50 and p95 for its normalized routes |
| Live global operator view | screenshots of the operator's Global web, Global API and Compare pages on the production data of those projects, with filter, sort and comparison in use (section 7) |
| Tenant-perspective video | one screen capture of a real project's account in production, recorded with that project's permission, following the script in section 8 |

The 14-day threshold goes beyond the RFP, which sets no duration. It is there so the proof shows
an installation that kept working, not a single afternoon of test visits. "Accepted,
proof-checked page views" means page views in a site's **primary** band. The gateway accepts no
event without a verified challenge proof ([../reference/browser-proof.md](https://docs.veristar.app/reference/browser-proof.md)),
so every stored event passed it. Page views that landed in the quarantine band are reported next
to the primary band and are never counted towards the threshold. A day the aggregation never read
breaks a run, like a day without page views.

Traffic generated by the project team, by scripts or by the platform's own probe does not count.
If a project's numbers on a day are mostly its own team's testing, leave that day out of the
claim and say so in the evidence pull request.

## 2. Choosing the projects

1. Draw up a list of SCF-awarded projects that run a public website or an HTTP API. Record, for
   each, the public source of its award (the link SCF publishes for it). A project whose award
   cannot be shown from a public SCF source is not used.
2. Prefer variety over size: different frameworks (static, SPA, server rendered) and, for the API
   project, a language with a tested guide ([../onboarding/overview.md](https://docs.veristar.app/onboarding/overview.md)).
3. Send each candidate the [pilot pack](https://docs.veristar.app/adoption/pilot-pack.md). Track each contact in the project's
   issue tracker as a waiting item (who was asked, when, the answer); a session cannot do the
   outreach.

## 3. Permission to appear

Before a project's name, numbers or screens appear in any evidence, a person who can speak for the
project gives written permission. It is given in a public place that can be linked (a comment on
the evidence pull request, or an issue in this repository) and covers each of these separately:

| Permission | Covers |
| - | - |
| Name | the project's name, slug and tenant id in `docs/adoption/` |
| Numbers | its daily web and API numbers in an evidence file |
| Operator screenshots | its row in screenshots of the operator views |
| Video | a recording of its own account and dashboards, published as a release asset |

A project may give some and refuse others. A project that gives none still counts as using the
service, but cannot be one of the three named projects. Permission can be withdrawn at any time:
then its rows are removed from the next evidence file, its screenshots are replaced, and a video
that shows it is removed from the release.

Record each permission in `docs/adoption/participants.md` when the first one exists, one row per
project:

| Column | Content |
| - | - |
| Project | the name as enrolled |
| Tenant id | from the console or `/tenants` (section 6) |
| SCF award | link to the public SCF source |
| Contact | GitHub login of the person who gave permission |
| Permissions | which of name, numbers, screenshots, video |
| Link | the public comment or issue that holds the permission |
| Enrolled | UTC day, from the evidence file |
| First data | first UTC day with accepted page views (web) or requests (API), from the evidence file |

## 4. Timeline

1. Production signed off as ready ([../deploy/production-readiness.md](https://docs.veristar.app/deploy/production-readiness.md), section 9).
2. Each project enrolls, adds its site and installs the snippet, or merges the pull request it was
   offered ([pilot-pack.md](https://docs.veristar.app/adoption/pilot-pack.md)). An operator confirms the first accepted page views
   in the project's row on Global web. The API project creates a token and adds the second
   exporter; requests appear on Global API with normalized routes.
3. A framework that has no tested example in [../onboarding/overview.md](https://docs.veristar.app/onboarding/overview.md) is
   checked on the real site, and its guide (new or updated) gets the date it was verified there.
4. Wait until every web project has 14 consecutive days. Run the report daily (section 6) to see
   where each run stands; do not commit those daily runs.
5. Generate the evidence file, take the screenshots, record the video, then open one pull request
   with all of it.

## 5. The evidence file

`docs/adoption/evidence-YYYY-MM-DD.md` is written by `cmd/adoptionreport` and never edited by
hand. For each tenant it holds:

* the summary: status, enrollment day, first accepted page view in the range, the longest run of
  consecutive days, whether the threshold is met, and the days with API requests;
* the seven web metrics of RFP 3.2 over the range: page views, unique visitors (the sum of daily
  unique visitors, [../reference/web-metrics.md](https://docs.veristar.app/reference/web-metrics.md)), session duration,
  bounce rate, and the top referrers, countries, devices, browsers and operating systems;
* every day of the range with its primary numbers, quarantined page views and whether it counts;
* for API traffic: requests, status below 400, 4xx and 5xx, and p50 and p95 per day (percentiles
  are never combined across days), plus every route of the newest day with requests;
* a source table: every machine API request the numbers came from, with the request id the
  control plane logged and the SHA-256 of the answer, so any number can be traced to the server's
  own log.

The command refuses an answer that has a field the contract
([../reference/openapi/metrics-v1.yaml](../reference/openapi/metrics-v1.yaml)) does not define,
an answer for another range than the one asked, and a tenant the key cannot see.

## 6. Extracting the numbers

Nothing in the evidence is typed by hand. An operator creates a key for this, uses it, and revokes
it afterwards ([../operators/api-keys.md](https://docs.veristar.app/operators/api-keys.md)).

1. Create a key in the console under **Operator, API keys**: name `adoption evidence`, scope
   `metrics:read` for all tenants, lifetime 30 days. Keep it in your shell only:

   ```sh theme={null}
   read -rs SA_OPERATOR_KEY && export SA_OPERATOR_KEY
   ```

2. Find the tenant ids:

   ```sh theme={null}
   curl -fsS -H "Authorization: Bearer $SA_OPERATOR_KEY" \
     "https://app.<input I4>/api/metrics/v1/tenants" \
     | python3 -c 'import json,sys; [print(t["id"], t["status"], t["name"]) for t in json.load(sys.stdin)["items"]]'
   ```

   If `next_cursor` is not `null`, repeat with `?cursor=<next_cursor>` appended.

3. Write the evidence for the participating tenants, over a range that holds the 14 days (the
   default is the 30 complete UTC days before today):

   ```sh theme={null}
   go run ./cmd/adoptionreport \
     -api "https://app.<input I4>/api/metrics/v1" \
     -tenants <id>,<id>,<id>,<id> \
     -raw resources/scratch/adoption-raw-$(date -u +%F)
   ```

   It prints the file it wrote and one line per tenant, for example
   `<id> <name>: longest run 16 days (2026-12-01 to 2026-12-16), meets the 14-day threshold; ...`.
   `-from` and `-to` set the range (at most 366 days, `-to` not after today), `-min-days` the
   threshold, `-out` the directory, `-force` replaces a file of the same day. `-raw` keeps every
   answer and an index of the requests outside the repository, for anyone who wants to check the
   hashes in the source table.

4. Check that every web tenant says `meets` and the API tenant has days with requests. If one
   does not, the proof is not complete; do not adjust the range to hide a gap inside it.

5. Revoke the key in the console.

The command and its contract tests are in `cmd/adoptionreport`. Its end-to-end path was run on
2026-11-13 against the local development stack (a local project, real browsers through the
tracker and gateway, the Go example app through the collector); that output is not evidence and
is not in this directory.

## 7. Screenshots

Taken in production by an operator, at a desktop window width of at least 1440 pixels, as PNG,
stored as `docs/adoption/screenshots/<YYYY-MM-DD>-<name>.png`. Every screenshot shows only
projects with screenshot permission. If another project would be visible, narrow the view with
the filters until it is not; never blur or edit a screenshot.

| Name | Page and state | Must show |
| - | - | - |
| `global-web` | Operator, Global web; range **Custom** covering the 14 days; filter "has web data in the range" on | a row for each of the three web projects with page views, visitors, bounce rate and average visit duration, and the referrer, country, device and browser columns |
| `global-web-sorted` | the same, sorted by visitors, largest first | the sort indicator on the visitors column and the three rows in that order |
| `global-web-compare` | tick the three web projects, **Compare** | the daily charts and the totals table of all three, side by side |
| `global-api` | Operator, Global API; same range; filter "has API data in the range" on | the API project's row with requests, 4xx and 5xx rates, p50, p95 and its source |
| `global-api-compare` | tick the API project (and others with API data), **Compare** | daily requests and p95, and the API project's services ordered by requests |
| `tenant-web-dashboard` | as a member of one web project, the site's web dashboard, range covering the 14 days | all seven metrics: visitors, views, bounce rate and visit duration in the metrics bar, and the sources, location and environment panels |
| `tenant-api-dashboard` | as a member of the API project, **API traffic** | requests, status codes, p50 and p95 per route |

Two numbers on each operator screenshot are checked against the evidence file of the same range
in the pull request description (for example page views and visitors of one project), so a
reviewer can see that the console and the machine API agree.

## 8. The tenant-perspective video

Recorded with the permission of one participating project, by a member of that project, on its
real account in production.

**Setup, so nothing private is captured:**

* Use a browser profile with no other tabs, extensions or bookmarks bar, signed in to GitHub as
  that member. The member's GitHub account must belong to **this project only** on the platform,
  so the console's project list shows nothing else.
* Record the page content only, never the address bar. Open the console as an app window without
  browser chrome (for Chromium: `chromium --app=https://app.<input I4>/`) and capture that window,
  or capture a screen region that excludes the toolbar. The single-sign-on step to the web
  dashboard passes a short-lived token in the address bar (`/sso?token=...`,
  [../compliance/privacy-strategy.md](https://docs.veristar.app/compliance/privacy-strategy.md)); it must never appear on
  screen.
* Sign in to GitHub before recording starts, so no GitHub password or two-factor code is typed on
  camera.
* 1920 by 1080, at least 30 frames per second, no audio or a voice-over without personal data.

**Script** (about four minutes):

| Step | Show | Say or caption |
| - | - | - |
| 1 | The console sign-in page, **Sign in with GitHub**, return to the console | Projects sign in with GitHub; no password is stored |
| 2 | The project's **Overview** | One project, its sites and its status |
| 3 | **Sites**, then **Snippet** for the site | One pinned script tag with an integrity hash; upgrades are deliberate |
| 4 | **Open web dashboard**; the dashboard opens (the address bar is not visible) | Single sign-on into the read-only dashboard |
| 5 | Pick a range covering at least 14 days | Real data over a selected range |
| 6 | Point at visitors, views, bounce rate, visit duration, then the referrer, country, device and browser panels | The seven required metrics |
| 7 | The **Quarantine view** of the same site | Suspicious traffic is kept apart, never deleted |
| 8 | Back in the console: **API traffic** (only if this project sends API data; otherwise skip and say so in the release notes) | Requests, status codes, p50 and p95 per route |
| 9 | **API analytics setup** with the token list; do not create a token on camera | Tokens are shown once and can be revoked |
| 10 | **Privacy** page | Erasure requests and the privacy settings of the project |

Before publishing, watch the whole recording once and check: no address bar during step 4, no
token, key or secret, no other project's name or data, no email address or GitHub notification.
If anything is visible, record again; do not edit it out.

**Publishing:** attach the file to a GitHub release of this repository and record its hash in the
evidence pull request:

```sh theme={null}
sha256sum tenant-video.mp4
gh release upload <release tag> tenant-video.mp4
```

## 9. The evidence pull request

One pull request adds, together: `participants.md`, the evidence file, the screenshots, and the
link to the release asset with its SHA-256. Its description lists the plan phase 20 checks and
how each is met:

* three web projects with at least 14 consecutive days and all seven metrics visible;
* the API project with volume, status distribution, p50 and p95 for normalized routes;
* the operator views listing all participating projects with filter, sort and comparison in use;
* the machine API returning their daily metrics with an operator key (the evidence file itself);
* the video showing the tenant experience on real data with no other tenant's data;
* the first production SLO report ([../runbooks/slo-report.md](https://docs.veristar.app/runbooks/slo-report.md));
* no critical alert open on the day the evidence was taken.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.