Creators paid by any platform
Your agent writes these files into openspec/changes/integrate-aisot-source-terms/ in your repo, runs openspec validate integrate-aisot-source-terms, and works the task list. The setup guide explains each step for people.
language: http · python · typescript with: none fits this use case
OPENSPEC/CHANGES/INTEGRATE-AISOT-SOURCE-TERMS/PROPOSAL.MD
# Proposal: Creators paid by any platform
## Why
Each platform runs its own creator program, and creators sign up one by one. A claim and a terms record here are read by every platform that adopts them, and payout records show who paid.
## What Changes
- The creator claims a domain, GitHub account or DOI and proves control.
- The creator publishes standing terms: deny, attribute or a royalty rate.
- A platform reads the terms, pays on its own rails, and publishes a payout record.
## Capabilities
### New Capabilities
- `source-terms`: Claim a domain once and publish signed terms. Platforms read them, pay on their own rails, and record the payout.
## Impact
- External service: AI Source of Truth at https://aisourceoftruth.com. Reads are anonymous. Writes need a publisher key pair you generate, a client id and secret from registration, and a token from `/oauth/token`.
- Routes used: `POST /v1/source-claims`, `POST /v1/source-claims/verify`, `POST /v1/terms`, `GET /v1/sources/{source_id}/terms`, `POST /v1/records`.
- No PromptReports product is required.
- Source of this plan: https://aisourceoftruth.com/use-cases/creators-paid (CC0). Regenerate it with `curl -H 'Accept: application/json' 'https://aisourceoftruth.com/use-cases/creators-paid/openspec?lang=http'`.
OPENSPEC/CHANGES/INTEGRATE-AISOT-SOURCE-TERMS/DESIGN.MD
# Design: Creators paid by any platform
## Context
Writers and creators, and the platforms that use their work. Each platform runs its own creator program, and creators sign up one by one. A claim and a terms record here are read by every platform that adopts them, and payout records show who paid.
## Where it sits in your agent
Creators do this once. Platforms put the terms read in the ingest step and the payout record in their monthly payout job.
Over MCP, point the agent at `https://aisourceoftruth.com/mcp` (Streamable HTTP, JSON-RPC 2.0; read tools need no token). The tools this change uses: `publish_record`, `lookup`.
## Decisions
- Treat the registry as a source of facts about records, never about the world. Show what it says, with the digest, and do not turn a verdict into a quality score.
- If the registry cannot be reached, treat the answer as unknown (the same as `check`), never as `rely`, and retry later.
- Keep content private: send hashes. Never put personal data in a record; it is public and permanent.
- Keep the private key and client secret in your secret store. Rotate keys at `POST /v1/keys`; a revoked key cannot sign.
## Setup and signing helper
```sh
# Publisher setup, once. Make an Ed25519 key pair yourself; the registry never sees the private key.
# 1. Register: POST https://aisourceoftruth.com/v1/publishers with {"id","name","public_jwk"}, signed by that key
# (X-AISOT-Signature over the exact body bytes, base64url) and an Idempotency-Key.
# The answer carries client_id, client_secret and your key_id.
# 2. Token (60 minutes; mint another the same way):
curl -s -X POST 'https://aisourceoftruth.com/oauth/token' -H 'Content-Type: application/json' \
--data '{"grant_type":"client_credentials","client_id":"'"$AISOT_CLIENT_ID"'","client_secret":"'"$AISOT_CLIENT_SECRET"'"}'
# ./sign-ed25519 reads bytes on stdin and prints the base64url Ed25519 signature.
```
## Calls
### POST /v1/source-claims
claim a source (pending until verified).
```sh
BODY='{"source_id":"{domain, github.com/owner or DOI}","method":"dns-txt","proof":"{proof}"}'
SIG=$(printf %s "$BODY" | ./sign-ed25519) # base64url signature over these exact bytes
curl -s -X POST 'https://aisourceoftruth.com/v1/source-claims' \
-H "Authorization: Bearer $AISOT_TOKEN" \
-H "X-AISOT-Key-Id: $AISOT_KEY_ID" \
-H "X-AISOT-Signature: $SIG" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data-binary "$BODY"
```
### POST /v1/source-claims/verify
check the claim's proof and promote it.
```sh
BODY='{"source_id":"{source id}"}'
SIG=$(printf %s "$BODY" | ./sign-ed25519) # base64url signature over these exact bytes
curl -s -X POST 'https://aisourceoftruth.com/v1/source-claims/verify' \
-H "Authorization: Bearer $AISOT_TOKEN" \
-H "X-AISOT-Key-Id: $AISOT_KEY_ID" \
-H "X-AISOT-Signature: $SIG" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data-binary "$BODY"
```
### POST /v1/terms
publish standing terms for a claimed source.
```sh
BODY='{"source_id":"{source id}","license_id":"AISOT-ATTRIB"}'
SIG=$(printf %s "$BODY" | ./sign-ed25519) # base64url signature over these exact bytes
curl -s -X POST 'https://aisourceoftruth.com/v1/terms' \
-H "Authorization: Bearer $AISOT_TOKEN" \
-H "X-AISOT-Key-Id: $AISOT_KEY_ID" \
-H "X-AISOT-Signature: $SIG" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
--data-binary "$BODY"
```
### GET /v1/sources/{source_id}/terms
read a source's standing terms.
```sh
curl -s -H 'Accept: application/json' 'https://aisourceoftruth.com/v1/sources/{source_id}/terms'
```
### POST /v1/records
append a signed record; the answer carries its digest and inclusion proof.
```sh
BODY='{ ...record }'
SIG=$(printf %s "$BODY" | ./sign-ed25519) # base64url signature over these exact bytes
curl -s -X POST 'https://aisourceoftruth.com/v1/records' \
-H "Authorization: Bearer $AISOT_TOKEN" \
-H "X-AISOT-Key-Id: $AISOT_KEY_ID" \
-H "X-AISOT-Signature: $SIG" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/vnd.aisot.record+json' \
--data-binary "$BODY"
```
## What this does not prove
- The registry records terms and payments. It never holds, moves or settles money.
OPENSPEC/CHANGES/INTEGRATE-AISOT-SOURCE-TERMS/TASKS.MD
# Tasks: Creators paid by any platform
## 1. Configure
- [ ] 1.1 Set `AISOT_ORIGIN=https://aisourceoftruth.com` in the agent's environment.
- [ ] 1.2 Generate an Ed25519 key pair, register the publisher (`POST /v1/publishers`), and store `AISOT_CLIENT_ID`, `AISOT_CLIENT_SECRET`, `AISOT_KEY_ID` and the private key as secrets.
- [ ] 1.3 Mint a token at `/oauth/token` and confirm `GET /v1/me` answers with your publisher id.
- [ ] 1.4 Optional: add the MCP server `https://aisourceoftruth.com/mcp` to the agent's MCP config.
## 2. Build
- [ ] 2.1 Claim the source: Claim your domain with DNS TXT (`_aisot.<domain>` carries `aisot-verify=<publisher_id>`), your GitHub account with OAuth, or a DOI. (`POST /v1/source-claims`)
- [ ] 2.2 Verify the claim: Run the verify call once the proof is in place. (`POST /v1/source-claims/verify`)
- [ ] 2.3 Publish terms: Choose `AISOT-DENY`, `AISOT-ATTRIB` or `AISOT-ROYALTY-{rate}` such as `AISOT-ROYALTY-0.05`. (`POST /v1/terms`)
- [ ] 2.4 Platforms read and pay: A platform reads the terms before use, pays on its own rails, and posts a `payout` record with source, period, amount as a string, currency and settlement provider. (`GET /v1/sources/{source_id}/terms`)
## 3. Verify against the live registry
- [ ] 3.1 Claim the source: The claim is listed as pending.
- [ ] 3.2 Verify the claim: The claim shows as verified.
- [ ] 3.3 Publish terms: The terms read back at the GET route.
- [ ] 3.4 Platforms read and pay: The source page lists the payout.
## 4. Done when
- [ ] 4.1 One claim makes a creator addressable by every adopting platform.
- [ ] 4.2 Payouts are public records any creator can check.
OPENSPEC/CHANGES/INTEGRATE-AISOT-SOURCE-TERMS/SPECS/SOURCE-TERMS/SPEC.MD
# source-terms Specification ## ADDED Requirements ### Requirement: Terms are read before use The platform SHALL read a claimed source's terms before using its work and SHALL exclude work under `AISOT-DENY`. #### Scenario: Royalty terms - **WHEN** a source's terms are `AISOT-ROYALTY-0.05` - **THEN** the platform accrues the royalty and later publishes a payout record
$ curl -H 'Accept: application/json' https://aisourceoftruth.com/use-cases/creators-paid/openspec?lang=http # this page is a rendering of the API. Reproduce it as data.