sello 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +83 -130
  2. package/docs/paper/notarized-agents.md +1 -1
  3. package/docs/paper/notarized-agents.tex +1 -1
  4. package/docs/protocol-walkthrough.md +74 -0
  5. package/docs/release-checklist.md +19 -3
  6. package/docs/sdk-quickstart.md +33 -3
  7. package/docs/sdk-security-audit.md +1 -1
  8. package/package.json +17 -17
  9. package/sdks/README.md +17 -0
  10. package/docs/sdk-build-plan.md +0 -214
  11. /package/{examples → sdks/typescript/examples}/mcp-minimal-server.ts +0 -0
  12. /package/{examples → sdks/typescript/examples}/mcp-tool-server.ts +0 -0
  13. /package/{examples → sdks/typescript/examples}/quickstart-tool.ts +0 -0
  14. /package/{fixtures → sdks/typescript/fixtures}/vectors/.gitkeep +0 -0
  15. /package/{fixtures → sdks/typescript/fixtures}/vectors/sello-v0.1.json +0 -0
  16. /package/{src → sdks/typescript/src}/cbor.ts +0 -0
  17. /package/{src → sdks/typescript/src}/cli/bench.ts +0 -0
  18. /package/{src → sdks/typescript/src}/cli/demo.ts +0 -0
  19. /package/{src → sdks/typescript/src}/cli/sello.ts +0 -0
  20. /package/{src → sdks/typescript/src}/cose/protected-header.ts +0 -0
  21. /package/{src → sdks/typescript/src}/cose/sign1.ts +0 -0
  22. /package/{src → sdks/typescript/src}/crypto/ed25519.ts +0 -0
  23. /package/{src → sdks/typescript/src}/crypto/identifiers.ts +0 -0
  24. /package/{src → sdks/typescript/src}/hpke/base.ts +0 -0
  25. /package/{src → sdks/typescript/src}/hpke/receipt.ts +0 -0
  26. /package/{src → sdks/typescript/src}/index.ts +0 -0
  27. /package/{src → sdks/typescript/src}/log/canonical-url.ts +0 -0
  28. /package/{src → sdks/typescript/src}/log/mock-log.ts +0 -0
  29. /package/{src → sdks/typescript/src}/log/rekor.ts +0 -0
  30. /package/{src → sdks/typescript/src}/log/types.ts +0 -0
  31. /package/{src → sdks/typescript/src}/mcp/middleware.ts +0 -0
  32. /package/{src → sdks/typescript/src}/owner/verify.ts +0 -0
  33. /package/{src → sdks/typescript/src}/receipt/body.ts +0 -0
  34. /package/{src → sdks/typescript/src}/registry/json-registry.ts +0 -0
  35. /package/{src → sdks/typescript/src}/sdk/index.ts +0 -0
  36. /package/{src → sdks/typescript/src}/sdk/keys.ts +0 -0
  37. /package/{src → sdks/typescript/src}/sdk/logs.ts +0 -0
  38. /package/{src → sdks/typescript/src}/sdk/publisher.ts +0 -0
  39. /package/{src → sdks/typescript/src}/sdk/service.ts +0 -0
  40. /package/{src → sdks/typescript/src}/service/create-receipt.ts +0 -0
  41. /package/{src → sdks/typescript/src}/token/jws-profile.ts +0 -0
package/README.md CHANGED
@@ -1,6 +1,31 @@
1
- ![Sello banner](docs/assets/sello-banner.png)
2
-
3
- # Sello
1
+ ![Sello banner](https://raw.githubusercontent.com/juanfiguera/sello/main/docs/assets/sello-banner.png)
2
+
3
+ <h1 align="center">Sello</h1>
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/juanfiguera/sello/actions/workflows/ci.yml"><img alt="build status" src="https://img.shields.io/github/actions/workflow/status/juanfiguera/sello/ci.yml?branch=main&style=flat-square&label=build&labelColor=0b1011&color=e8f7ef"></a>
7
+ <a href="https://www.npmjs.com/package/sello"><img alt="npm version" src="https://img.shields.io/npm/v/sello?style=flat-square&label=npm&labelColor=0b1011&color=e8f7ef"></a>
8
+ <a href="https://pypi.org/project/sello/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/sello?style=flat-square&label=pypi&labelColor=0b1011&color=e8f7ef"></a>
9
+ <a href="https://www.npmjs.com/package/sello"><img alt="npm downloads" src="https://img.shields.io/npm/dm/sello?style=flat-square&label=downloads&labelColor=0b1011&color=e8f7ef"></a>
10
+ <a href="LICENSE"><img alt="license Apache-2.0" src="https://img.shields.io/npm/l/sello?style=flat-square&label=license&labelColor=0b1011&color=e8f7ef"></a>
11
+ <a href="package.json"><img alt="Node.js 22.7 or newer" src="https://img.shields.io/badge/node-%3E%3D22.7-e8f7ef?style=flat-square&labelColor=0b1011"></a>
12
+ <a href="sdks/python/pyproject.toml"><img alt="Python 3.9 or newer" src="https://img.shields.io/badge/python-%3E%3D3.9-e8f7ef?style=flat-square&labelColor=0b1011"></a>
13
+ <a href="https://arxiv.org/abs/2606.04193"><img alt="arXiv 2606.04193" src="https://img.shields.io/badge/arXiv-2606.04193-e8f7ef?style=flat-square&labelColor=0b1011"></a>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="#try-it">Quickstart</a> &middot;
18
+ <a href="#add-sello-to-a-tool">Add Sello</a> &middot;
19
+ <a href="sdks/README.md">SDKs</a> &middot;
20
+ <a href="#see-logged-actions">Actions</a> &middot;
21
+ <a href="#how-it-works">How It Works</a> &middot;
22
+ <a href="#learn-more">Learn More</a> &middot;
23
+ <a href="SPEC.md">Protocol</a> &middot;
24
+ <a href="https://arxiv.org/abs/2606.04193">Paper</a> &middot;
25
+ <a href="SECURITY.md">Security</a> &middot;
26
+ <a href="CONTRIBUTING.md">Contributing</a> &middot;
27
+ <a href="#license">License</a>
28
+ </p>
4
29
 
5
30
  Sello is a protocol for independently-verifiable records of AI agent actions.
6
31
 
@@ -36,76 +61,16 @@ Then open:
36
61
  http://localhost:8787/actions
37
62
  ```
38
63
 
39
- To see the tiny wrapped-tool source:
64
+ `sello dev` creates local keys, a demo token, a service registry, and a local transparency log under `.sello/`. The log stores encrypted receipt entries, not plaintext action details.
40
65
 
41
- ```bash
42
- npx --yes sello init-demo
43
- ```
66
+ ## Add Sello to a Tool
44
67
 
45
- To scaffold a small HTTP route that emits receipts:
68
+ TypeScript:
46
69
 
47
70
  ```bash
48
- npx --yes sello init-http-demo
49
- npx --yes sello call-http-demo
71
+ npm install sello
50
72
  ```
51
73
 
52
- ## What Just Happened?
53
-
54
- `sello dev` created a local owner key, service key, token, registry, and transparency log. The demo tool or route verified the token before running the handler. After the handler ran, the service signed an encrypted receipt for the action it observed. The local log stored the encrypted receipt, not plaintext action details. `sello actions` fetched the receipt, verified the log entry and service signature, decrypted it with the owner key, and printed the owner's view.
55
-
56
- Local dev state lives under `.sello/`. The dev log is stored as encrypted receipt entries in `.sello/dev-log.jsonl`, so receipts survive restarting `sello dev` while staying out of git.
57
-
58
- ## Why Sello?
59
-
60
- Most agent logs are written by the same system whose behavior they describe. If the agent, runtime, or operator is compromised, those logs can be incomplete or false.
61
-
62
- Sello moves receipt-writing to the services the agent calls. The service was present for the action, but it is outside the agent's own logging path. The architectural inversion is simple: the signer is not the agent or its operator, but the receiver that observed the action.
63
-
64
- ## What Sello Gives You
65
-
66
- Sello helps an owner verify that:
67
-
68
- - A specific service signed a specific receipt.
69
- - The receipt was encrypted for the owner.
70
- - The receipt was included in a trusted transparency log.
71
- - The receipt body was not modified after signing.
72
-
73
- Sello does not prove that the agent called every service it should have called, that every service is honest, or that unauthenticated log indexes returned complete results. Those limits are intentional and documented in the spec.
74
-
75
- ## Repository Status
76
-
77
- This repository currently contains:
78
-
79
- - [SPEC.md](SPEC.md): the Sello protocol draft.
80
- - A TypeScript reference implementation in [`src/`](src/).
81
- - Implementation-backed v0.1 test vectors in [`fixtures/vectors/sello-v0.1.json`](fixtures/vectors/sello-v0.1.json).
82
- - Security review notes in [`docs/security-review.md`](docs/security-review.md).
83
- - SDK security audit notes in [`docs/sdk-security-audit.md`](docs/sdk-security-audit.md).
84
-
85
- The implementation includes a local end-to-end demo, compact JWS token verification, COSE_Sign1 receipt envelopes, HPKE encryption, a mock transparency log, a Rekor discovery adapter, owner verification, an MCP middleware prototype, security review notes, and a local benchmark. Live Rekor proof verification and production identity operations are still future work.
86
-
87
- 📄 **Paper:** [Notarized Agents: Receiver-Attested Confidential Receipts for AI Agent Actions](https://arxiv.org/abs/2606.04193) (arXiv:2606.04193, submitted June 2026). Local PDF: [docs/paper/notarized-agents.pdf](docs/paper/notarized-agents.pdf).
88
-
89
- ## Start Here
90
-
91
- | Goal | Read |
92
- |------|------|
93
- | Add Sello in a few lines | [SDK Quickstart](docs/sdk-quickstart.md) |
94
- | Emit your first receipt | `npx --yes sello dev`, then `npx --yes sello emit-demo` |
95
- | Wrap one HTTP route | `npx --yes sello init-http-demo`, then `npx --yes sello call-http-demo` |
96
- | Try a wrapped tool locally | `node --run dev`, then `node --run example:tool` |
97
- | Try an MCP-style tool call | `node --run dev`, then `node --run example:mcp` |
98
- | See a minimal MCP integration | [examples/mcp-minimal-server.ts](examples/mcp-minimal-server.ts) |
99
- | Understand the protocol | [SPEC.md](SPEC.md) Quick Start |
100
- | Run the local demo | `node --run demo` |
101
- | Run the test suite | `node --run test` |
102
- | Measure local size/performance | `node --run bench -- --json` |
103
- | Emit receipts from a service | [SPEC.md](SPEC.md) §§3.1, 4.1, 5, 6.2 |
104
- | Verify receipts as an owner | [SPEC.md](SPEC.md) §§4.2, 5, 6.2, 7.1 |
105
- | Build the reference implementation | Start with "The First 10 Minutes" below |
106
-
107
- ## Add Sello in a Few Lines
108
-
109
74
  ```ts
110
75
  import { sello } from "sello";
111
76
 
@@ -116,96 +81,84 @@ export const createEvent = receipts.tool("calendar.create_event", async (request
116
81
  });
117
82
  ```
118
83
 
119
- Then inspect verified actions:
84
+ Python:
120
85
 
121
86
  ```bash
122
- npx sello actions --token <agent-token>
87
+ pip install sello
123
88
  ```
124
89
 
125
- In local dev, `sello dev` prints and saves a demo token:
90
+ ```py
91
+ import sello
126
92
 
127
- ```bash
128
- SELLO_ACTION_TOKEN=eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...
129
- ```
130
-
131
- You usually do not need to copy it. `npx sello actions` reads the latest dev token from `.sello/dev.json`. Use `--token` when you want to inspect receipts for a specific agent authorization token from your own system.
93
+ receipts = sello.service()
132
94
 
133
- Sello works with your own log server. `sello.build` is optional convenience, not a protocol requirement.
95
+ @receipts.tool("calendar.create_event")
96
+ def create_event(request):
97
+ return calendar.events.create(request)
98
+ ```
134
99
 
135
- To try the repo's local loop:
100
+ In local dev, `npx sello dev` supplies the config this snippet needs. In production, configure your service with a service id, service signing key, token issuer, and log URL:
136
101
 
137
102
  ```bash
138
- # Terminal 1
139
- node --run dev
140
-
141
- # Terminal 2
142
- node --run example:tool
143
- node --run actions
103
+ SELLO_SERVICE_ID=calendar.example.com/mcp/v1
104
+ SELLO_SERVICE_KEY=sello_live_local_...
105
+ SELLO_TOKEN_ISSUER_JWKS=https://auth.example.com/.well-known/jwks.json
106
+ SELLO_LOG_URL=https://logs.example.com/api
107
+ SELLO_SUBMIT_MODE=background
144
108
  ```
145
109
 
146
- The example wraps a fake calendar tool, emits a service-signed encrypted receipt, and lets the owner verify it from the local action log.
147
-
148
- For an MCP-shaped `tools/call` boundary, run `node --run example:mcp` instead of `node --run example:tool`.
110
+ Sello works with your own log server. Using `sello.build` is an optional convenience, not a protocol requirement.
149
111
 
150
- For a smaller production-shaped MCP example, see [examples/mcp-minimal-server.ts](examples/mcp-minimal-server.ts). It wraps one `tools/call` handler with `sello.service()` and leaves unknown tools unreceipted.
112
+ To scaffold a tiny emitter or HTTP route:
151
113
 
152
- For an installed-project bridge from demo to app, run `npx sello init-http-demo`. It writes a small dependency-free HTTP route that imports `sello`, reads the local dev config, verifies a bearer token, runs a handler, and emits a receipt. With the local log and route running, `npx sello call-http-demo` sends the demo request for you.
114
+ ```bash
115
+ npx --yes sello init-demo
116
+ npx --yes sello init-http-demo
117
+ ```
153
118
 
154
- ## The First 10 Minutes
119
+ ## See Logged Actions
155
120
 
156
- If you are implementing Sello, start with one local loop:
121
+ ```bash
122
+ npx sello actions
123
+ ```
157
124
 
158
- 1. Generate a fixed owner HPKE key pair.
159
- 2. Generate a fixed service Ed25519 signing key.
160
- 3. Create one mock compact JWS token containing `owner_hpke_pk` and `sello_logs`.
161
- 4. Have the service create one receipt for one fake action.
162
- 5. Store the receipt in a mock log under `sello_token_ref`.
163
- 6. Have the owner fetch, verify, and decrypt the receipt.
125
+ In local dev, `sello actions` reads the latest dev token and owner key from `.sello/dev.json`. To inspect actions for a specific agent token, pass it explicitly:
164
126
 
165
- Do not start with Rekor, MCP middleware, distributed identity, or CLI polish. Those become much easier once one local receipt works end to end.
127
+ ```bash
128
+ npx sello actions --token <agent-token>
129
+ ```
166
130
 
167
- You know the first loop works when the owner can print one verified receipt:
131
+ The token is the same authorization token the agent used when it called services. Sello hashes the exact token bytes into `sello_token_ref`, queries trusted logs, verifies matching receipts, and decrypts them with the owner key.
168
132
 
169
- ```json
170
- {
171
- "service": "example.com/tool/v1",
172
- "action-type": "tools/call",
173
- "result-status": "success",
174
- "verified": true
175
- }
176
- ```
133
+ Public logs store encrypted receipts. Viewing action details requires the owner private key or an explicitly delegated viewer key.
177
134
 
178
- ## Service Integration
135
+ ## How It Works
179
136
 
180
- A Sello-aware service does this for each agent action:
137
+ Most agent logs are written by the same system whose behavior they describe. If the agent, runtime, or operator is compromised, those logs can be incomplete or false.
181
138
 
182
- 1. Verify the agent's authorization token.
183
- 2. Read `owner_hpke_pk` and `sello_logs` from the verified token.
184
- 3. Compute `sello_token_ref = SHA-256(raw compact JWS bytes)`.
185
- 4. Build a CBOR receipt body describing the action.
186
- 5. Encrypt the receipt body to the owner with HPKE.
187
- 6. Sign the COSE_Sign1 envelope with the service key.
188
- 7. Publish the envelope to an owner-trusted transparency log.
139
+ Sello moves receipt-writing to the services the agent calls. The service was present for the action, but it is outside the agent's own logging path.
189
140
 
190
- The service signs what it observed. It does not need the owner's private key, and it does not need to understand the owner's downstream audit workflow.
141
+ 1. The agent calls a service with an authorization token.
142
+ 2. The service verifies the token, runs the action, and signs an encrypted receipt for what it observed.
143
+ 3. A transparency log stores the encrypted receipt.
144
+ 4. The owner later fetches, verifies, and decrypts the receipt.
191
145
 
192
- For most services, Sello should fit as middleware around an existing request handler: verify token, run action, emit receipt.
146
+ Sello helps an owner verify that a specific service signed a specific receipt, the receipt was encrypted for the owner, the receipt was included in a trusted transparency log, and the receipt body was not modified after signing.
193
147
 
194
- ## Owner Verification
148
+ Sello does not prove that the agent called every service it should have called, that every service is honest, or that unauthenticated log indexes returned complete results. Those limits are intentional and documented in the spec.
195
149
 
196
- An owner verifier does this when reconstructing activity:
150
+ ## Learn More
197
151
 
198
- 1. Compute `sello_token_ref` from the same raw compact JWS bytes.
199
- 2. Query every trusted log for matching receipts.
200
- 3. Confirm each receipt's `sello_log_url` exactly matches the log that returned the proof.
201
- 4. Verify log inclusion.
202
- 5. Resolve the service signing key from `kid`.
203
- 6. Apply revocation rules using log integrated time.
204
- 7. Verify the COSE signature.
205
- 8. Decrypt the HPKE payload.
206
- 9. Validate and display the receipt body.
152
+ - [SDK Quickstart](docs/sdk-quickstart.md): local dev, HTTP demo, self-hosted config, and hosted config.
153
+ - [SDKs](sdks/README.md): TypeScript and Python package layout.
154
+ - [Python SDK](sdks/python/README.md): Python package install command, scope, and test command.
155
+ - [Protocol Walkthrough](docs/protocol-walkthrough.md): the primitive receipt loop for implementers.
156
+ - [SPEC.md](SPEC.md): the Sello protocol draft.
157
+ - [Notarized Agents paper](https://arxiv.org/abs/2606.04193): design rationale, threat model, and prior art.
158
+ - [sdks/typescript/examples/mcp-minimal-server.ts](sdks/typescript/examples/mcp-minimal-server.ts): a small MCP-shaped integration.
159
+ - [docs/security-review.md](docs/security-review.md) and [docs/sdk-security-audit.md](docs/sdk-security-audit.md): current review notes.
207
160
 
208
- For most owners, Sello should fit as a pull-based audit tool: provide the token and owner key, then retrieve the verified trail from trusted logs.
161
+ The TypeScript SDK is published on [npm](https://www.npmjs.com/package/sello) and lives in [`sdks/typescript/`](sdks/typescript/). The Python SDK is published on [PyPI](https://pypi.org/project/sello/) and lives in [`sdks/python/`](sdks/python/). Live Rekor proof verification and production identity operations are still future work.
209
162
 
210
163
  ## Core Terms
211
164
 
@@ -235,7 +188,7 @@ Much of this prior work surfaced after Sello's design had already converged on s
235
188
 
236
189
  ## Feedback
237
190
 
238
- Issues and pull requests are welcome. This is an early draft; adversarial review is the point.
191
+ Issues and pull requests are welcome. This is an early draft; adversarial review is the point. See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution notes and [SECURITY.md](SECURITY.md) for sensitive reports.
239
192
 
240
193
  ## License
241
194
 
@@ -323,7 +323,7 @@ We present first-party microbenchmarks of the cryptographic operations Sello per
323
323
 
324
324
  ### 7.1 Methodology
325
325
 
326
- The reference implementation [@sello-repo] ships with a benchmark tool (`src/cli/bench.ts`) that exercises the full receipt lifecycle. For each iteration the bench: (1) constructs a verified compact JWS authorization token, (2) creates a Sello receipt at the service side (HPKE seal of the CBOR-encoded receipt body to the owner's X25519 public key, followed by COSE_Sign1 signing with the service's Ed25519 private key), (3) submits the signed envelope to an in-process mock transparency log that returns an inclusion proof, and (4) performs full owner-side verification (proof verification, registry resolution, COSE_Sign1 signature verification, HPKE open, and receipt body validation). The mock log replaces network submission with deterministic in-process bookkeeping; this isolates the cryptographic costs from log-operator-specific network latency. Log submission latency to a hosted public log is discussed separately in §7.3.
326
+ The reference implementation [@sello-repo] ships with a benchmark tool (`sdks/typescript/src/cli/bench.ts`) that exercises the full receipt lifecycle. For each iteration the bench: (1) constructs a verified compact JWS authorization token, (2) creates a Sello receipt at the service side (HPKE seal of the CBOR-encoded receipt body to the owner's X25519 public key, followed by COSE_Sign1 signing with the service's Ed25519 private key), (3) submits the signed envelope to an in-process mock transparency log that returns an inclusion proof, and (4) performs full owner-side verification (proof verification, registry resolution, COSE_Sign1 signature verification, HPKE open, and receipt body validation). The mock log replaces network submission with deterministic in-process bookkeeping; this isolates the cryptographic costs from log-operator-specific network latency. Log submission latency to a hosted public log is discussed separately in §7.3.
327
327
 
328
328
  The cryptographic primitives are Node.js bindings to the system OpenSSL: X25519 key agreement and Ed25519 signing via `node:crypto`, ChaCha20-Poly1305 AEAD via `createCipheriv`, HKDF-SHA256 via `createHmac`, and SHA-256 via `createHash`. HPKE is implemented per RFC 9180 base mode with the suite specified in §2.1; the implementation is pinned to RFC 9180 Appendix A.2.1 test vectors and validated in the test suite.
329
329
 
@@ -994,7 +994,7 @@ on the Sello protocol itself.
994
994
  \subsubsection{7.1 Methodology}\label{methodology}}
995
995
 
996
996
  The reference implementation \citep{sello-repo} ships with a benchmark
997
- tool (\texttt{src/cli/bench.ts}) that exercises the full receipt
997
+ tool (\texttt{sdks/typescript/src/cli/bench.ts}) that exercises the full receipt
998
998
  lifecycle. For each iteration the bench: (1) constructs a verified
999
999
  compact JWS authorization token, (2) creates a Sello receipt at the
1000
1000
  service side (HPKE seal of the CBOR-encoded receipt body to the owner's
@@ -0,0 +1,74 @@
1
+ # Protocol Walkthrough
2
+
3
+ This guide is for people implementing Sello itself or studying the receipt flow below the SDK. If you only want to try Sello or add it to a service, start with the README or [`docs/sdk-quickstart.md`](sdk-quickstart.md).
4
+
5
+ ## Goal
6
+
7
+ Build the smallest complete Sello loop:
8
+
9
+ 1. One mock action happens.
10
+ 2. The service creates one encrypted signed receipt.
11
+ 3. A mock transparency log stores it under `sello_token_ref`.
12
+ 4. The owner fetches, verifies, and decrypts it.
13
+
14
+ Run the complete loop first:
15
+
16
+ ```bash
17
+ node --run demo
18
+ ```
19
+
20
+ The runnable source is [`sdks/typescript/src/cli/demo.ts`](../sdks/typescript/src/cli/demo.ts).
21
+
22
+ ## Local Pieces
23
+
24
+ The primitive loop needs these pieces:
25
+
26
+ | Piece | Local helper | Why it exists |
27
+ |-------|--------------|---------------|
28
+ | Owner key | `generateHpkeKeyPair()` | The public key goes in the token. The private key decrypts receipts later. |
29
+ | Service key | `generateEd25519KeyPair()` | The service signs receipts for actions it observed. |
30
+ | Token issuer key | `generateEd25519KeyPair()` | The issuer signs the mock agent token. |
31
+ | Transparency log | `new MockTransparencyLog(...)` | The log stores encrypted signed receipts by `sello_token_ref`. |
32
+ | Service registry | `loadSignedRegistry(...)` | The owner uses it to resolve service public keys and revocation status. |
33
+
34
+ Start with the owner key:
35
+
36
+ ```ts
37
+ import { base64urlEncode, generateHpkeKeyPair } from "sello";
38
+
39
+ const owner = generateHpkeKeyPair();
40
+ const ownerHpkePk = base64urlEncode(owner.publicKey);
41
+ ```
42
+
43
+ Put `ownerHpkePk` in the token's `owner_hpke_pk` claim. Keep `owner.privateKey` for the owner verifier.
44
+
45
+ Then create the other local pieces:
46
+
47
+ ```ts
48
+ import { generateEd25519KeyPair, MockTransparencyLog } from "sello";
49
+
50
+ const service = generateEd25519KeyPair();
51
+ const tokenIssuer = generateEd25519KeyPair();
52
+ const trustRoot = generateEd25519KeyPair();
53
+ const log = new MockTransparencyLog("https://rekor.example.com/api");
54
+ ```
55
+
56
+ ## Flow
57
+
58
+ 1. Sign a compact JWS token with `signSelloJwsToken(...)`.
59
+ 2. Include `owner_hpke_pk` and `sello_logs` in the signed token.
60
+ 3. Create a receipt with `createReceiptFromJwsToken(...)`.
61
+ 4. Verify with `verifyReceipts(...)` using the same raw token, owner private key, mock log, and service registry.
62
+
63
+ You know the loop works when the owner can print one verified receipt:
64
+
65
+ ```json
66
+ {
67
+ "service": "example.com/tool/v1",
68
+ "action-type": "tools/call",
69
+ "result-status": "success",
70
+ "verified": true
71
+ }
72
+ ```
73
+
74
+ Do not start with Rekor, MCP middleware, distributed identity, or CLI polish. Those become much easier once one local receipt works end to end.
@@ -1,6 +1,6 @@
1
1
  # Release Checklist
2
2
 
3
- Use this checklist before publishing a Sello npm release.
3
+ Use this checklist before publishing a Sello release.
4
4
 
5
5
  ## Preflight
6
6
 
@@ -8,6 +8,7 @@ Use this checklist before publishing a Sello npm release.
8
8
  - Confirm `node -v` is `v22.7.0` or newer.
9
9
  - If multiple Node versions are installed, confirm `PATH` resolves `node` to Node 22.7 or newer before running package scripts.
10
10
  - Confirm `package.json` has the intended version.
11
+ - Confirm `sdks/python/pyproject.toml` has the intended version when publishing Python.
11
12
  - Confirm `README.md` and `docs/sdk-quickstart.md` match the current CLI and examples.
12
13
  - Confirm the paper link and local PDF are current, if the paper changed.
13
14
 
@@ -28,8 +29,8 @@ node -v # must be v22.7.0 or newer
28
29
  node --run test
29
30
  node --run package:test
30
31
  npm pack --dry-run
31
- node --experimental-strip-types src/cli/sello.ts --help
32
- node --experimental-strip-types src/cli/sello.ts dev --dry-run
32
+ node --experimental-strip-types sdks/typescript/src/cli/sello.ts --help
33
+ node --experimental-strip-types sdks/typescript/src/cli/sello.ts dev --dry-run
33
34
  ```
34
35
 
35
36
  ## npm Verification
@@ -42,6 +43,19 @@ npm publish --dry-run
42
43
 
43
44
  If the package name is already published, confirm the local version is greater than the registry version before publishing.
44
45
 
46
+ ## PyPI Verification
47
+
48
+ ```bash
49
+ python -m pip install --upgrade build twine
50
+ cd sdks/python
51
+ rm -rf dist
52
+ python -m build
53
+ python -m twine check dist/*
54
+ ```
55
+
56
+ The PyPI project uses trusted publishing from `.github/workflows/release.yml`.
57
+ Publishing a GitHub Release for a version tag triggers the PyPI publish job. Use the manual workflow dispatch only when you intentionally want to publish Python without creating a GitHub Release; rerunning the same version is safe because the workflow skips files that already exist on PyPI.
58
+
45
59
  ## Publish
46
60
 
47
61
  ```bash
@@ -53,5 +67,7 @@ git push origin main --tags
53
67
  After publishing:
54
68
 
55
69
  - Confirm `npm view sello version` shows the new version.
70
+ - Publish a GitHub Release for the pushed tag so PyPI trusted publishing runs.
71
+ - Confirm `python -m pip index versions sello` shows the new version after PyPI publishing.
56
72
  - Confirm `npx sello --help` works from a clean temp directory.
57
73
  - Confirm GitHub Actions passes on `main`.
@@ -2,7 +2,15 @@
2
2
 
3
3
  Sello's SDK is designed to make the first receipt easy: wrap a tool handler, run it, and inspect verified actions.
4
4
 
5
- Requires Node.js 22.7 or newer.
5
+ The local demo CLI and action viewer require Node.js 22.7 or newer. The Python SDK requires Python 3.9 or newer.
6
+
7
+ ## Install
8
+
9
+ TypeScript:
10
+
11
+ ```bash
12
+ npm install sello
13
+ ```
6
14
 
7
15
  ```ts
8
16
  import { sello } from "sello";
@@ -14,6 +22,22 @@ export const createEvent = receipts.tool("calendar.create_event", async (request
14
22
  });
15
23
  ```
16
24
 
25
+ Python:
26
+
27
+ ```bash
28
+ pip install sello
29
+ ```
30
+
31
+ ```py
32
+ import sello
33
+
34
+ receipts = sello.service()
35
+
36
+ @receipts.tool("calendar.create_event")
37
+ def create_event(request):
38
+ return calendar.events.create(request)
39
+ ```
40
+
17
41
  The service process emits receipts. It does not need the owner private key.
18
42
 
19
43
  ## Local Development
@@ -54,6 +78,12 @@ npx --yes sello actions
54
78
 
55
79
  Local dev state lives under `.sello/`. The encrypted dev log is stored in `.sello/dev-log.jsonl`, so receipts survive restarting `sello dev` without being committed to git.
56
80
 
81
+ ## Troubleshooting
82
+
83
+ - **Port already in use:** run `npx sello dev --port 8791`.
84
+ - **No actions found:** make sure `sello dev` is running from the same project folder where you emitted the receipt.
85
+ - **Missing token:** run `npx sello dev` first so `.sello/dev.json` exists.
86
+
57
87
  Inside this repo, start the local log and action viewer:
58
88
 
59
89
  ```bash
@@ -80,9 +110,9 @@ or open:
80
110
  http://localhost:8787/actions
81
111
  ```
82
112
 
83
- Both examples read `.sello/dev.json`, wrap a fake calendar handler, submit one encrypted receipt, and let the owner verify it locally.
113
+ Both examples read `.sello/dev.json`, wrap a mock calendar handler, submit one encrypted receipt, and let the owner verify it locally.
84
114
 
85
- For the smallest production-shaped MCP boundary, see [`examples/mcp-minimal-server.ts`](../examples/mcp-minimal-server.ts). It wraps one `tools/call` handler with `sello.service()` and leaves unknown tools unreceipted.
115
+ For the smallest production-shaped MCP boundary, see [`sdks/typescript/examples/mcp-minimal-server.ts`](../sdks/typescript/examples/mcp-minimal-server.ts). It wraps one `tools/call` handler with `sello.service()` and leaves unknown tools unreceipted.
86
116
 
87
117
  For your own tool server, copy the printed service env:
88
118
 
@@ -7,7 +7,7 @@ These notes cover the first Stripe-style SDK implementation pass. They are writt
7
7
  - Service emission and owner viewing are documented as separate environments.
8
8
  - The service process is not required to hold `SELLO_OWNER_KEY`.
9
9
  - Hosted `sello.build` is described as optional convenience, not as a protocol dependency.
10
- - Deferred production features are named in `docs/sdk-build-plan.md`.
10
+ - Deferred production features are named in the README, quickstart, and this audit note.
11
11
 
12
12
  ## Phase 1: Env-First Facade
13
13
 
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "sello",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Reference implementation of the Sello protocol for service-signed AI agent receipts.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "sideEffects": false,
8
8
  "exports": {
9
9
  ".": "./dist/index.js",
10
- "./fixtures/vectors/sello-v0.1.json": "./fixtures/vectors/sello-v0.1.json",
10
+ "./fixtures/vectors/sello-v0.1.json": "./sdks/typescript/fixtures/vectors/sello-v0.1.json",
11
11
  "./spec": "./SPEC.md",
12
12
  "./package.json": "./package.json"
13
13
  },
@@ -18,27 +18,27 @@
18
18
  },
19
19
  "files": [
20
20
  "dist",
21
- "examples",
22
- "src",
23
- "fixtures/vectors",
21
+ "sdks/typescript/examples",
22
+ "sdks/typescript/src",
23
+ "sdks/typescript/fixtures/vectors",
24
24
  "docs",
25
25
  "SPEC.md",
26
26
  "README.md",
27
27
  "LICENSE"
28
28
  ],
29
29
  "scripts": {
30
- "actions": "node --experimental-strip-types src/cli/sello.ts actions",
31
- "bench": "node --experimental-strip-types src/cli/bench.ts",
32
- "demo": "node --experimental-strip-types src/cli/demo.ts",
33
- "dev": "node --experimental-strip-types src/cli/sello.ts dev",
34
- "example:mcp:minimal": "node --test --experimental-strip-types test/examples/mcp-minimal-server.test.ts",
35
- "example:mcp": "node --experimental-strip-types examples/mcp-tool-server.ts",
36
- "example:tool": "node --experimental-strip-types examples/quickstart-tool.ts",
37
- "build": "node --disable-warning=ExperimentalWarning scripts/build-dist.mjs",
38
- "package:test": "node scripts/package-smoke.mjs",
39
- "pack:check": "npm pack --dry-run",
40
- "prepack": "node --disable-warning=ExperimentalWarning scripts/build-dist.mjs",
41
- "test": "node --test --experimental-strip-types"
30
+ "actions": "node --experimental-strip-types sdks/typescript/src/cli/sello.ts actions",
31
+ "bench": "node --experimental-strip-types sdks/typescript/src/cli/bench.ts",
32
+ "demo": "node --experimental-strip-types sdks/typescript/src/cli/demo.ts",
33
+ "dev": "node --experimental-strip-types sdks/typescript/src/cli/sello.ts dev",
34
+ "example:mcp:minimal": "node --test --experimental-strip-types sdks/typescript/test/examples/mcp-minimal-server.test.ts",
35
+ "example:mcp": "node --experimental-strip-types sdks/typescript/examples/mcp-tool-server.ts",
36
+ "example:tool": "node --experimental-strip-types sdks/typescript/examples/quickstart-tool.ts",
37
+ "build": "node --disable-warning=ExperimentalWarning sdks/typescript/scripts/build-dist.mjs",
38
+ "package:test": "node sdks/typescript/scripts/package-smoke.mjs",
39
+ "pack:check": "node sdks/typescript/scripts/pack-check.mjs",
40
+ "prepack": "node --disable-warning=ExperimentalWarning sdks/typescript/scripts/build-dist.mjs",
41
+ "test": "cd sdks/typescript && node --test --experimental-strip-types"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=22.7.0"
package/sdks/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # Sello SDKs
2
+
3
+ The protocol, paper, and project docs live at the repository root. Language SDKs live here:
4
+
5
+ - [`typescript/`](typescript/): npm package source, CLI, examples, fixtures, and Node tests.
6
+ - [`python/`](python/): Python package source and tests.
7
+
8
+ Root commands still work from the repository top level:
9
+
10
+ ```bash
11
+ node --run test
12
+ node --run package:test
13
+ python -m pip install ./sdks/python
14
+ python -m unittest discover -s sdks/python/tests
15
+ ```
16
+
17
+ This keeps the first screen of the repo focused on the protocol while giving each language a predictable home.
@@ -1,214 +0,0 @@
1
- # Stripe-Style Sello SDK Integration Plan
2
-
3
- ## Summary
4
-
5
- Build the first Sello SDK around a complete, Stripe-like loop:
6
-
7
- 1. Add one import.
8
- 2. Call `sello.service()`.
9
- 3. Wrap an existing tool handler.
10
- 4. Run the tool.
11
- 5. See verified logged actions.
12
-
13
- Quickstart service code:
14
-
15
- ```ts
16
- import { sello } from "sello";
17
-
18
- const receipts = sello.service();
19
-
20
- export const createEvent = receipts.tool("calendar.create_event", async (request) => {
21
- return calendar.events.create(request);
22
- });
23
- ```
24
-
25
- Quickstart viewing:
26
-
27
- ```bash
28
- npx sello actions --token <agent-token>
29
- ```
30
-
31
- Local dev can also show:
32
-
33
- ```text
34
- http://localhost:8787/actions
35
- ```
36
-
37
- Sello must work without `sello.build`. Self-hosting is first-class. Hosted `sello.build` is optional convenience.
38
-
39
- ## Configuration Model
40
-
41
- Keep service emission and owner viewing separate.
42
-
43
- ### Service Runtime Env
44
-
45
- Used by the app/tool server that emits receipts.
46
-
47
- Self-hosted development:
48
-
49
- ```bash
50
- SELLO_SERVICE_ID=calendar.example.com/mcp/v1
51
- SELLO_SERVICE_KEY=sello_dev_...
52
- SELLO_TOKEN_ISSUER_PUBLIC_KEY=...
53
- SELLO_LOG_URL=https://localhost:8787/api
54
- SELLO_LOG_ENDPOINT=http://localhost:8787/api
55
- SELLO_SUBMIT_MODE=background
56
- ```
57
-
58
- Self-hosted production:
59
-
60
- ```bash
61
- SELLO_SERVICE_ID=calendar.example.com/mcp/v1
62
- SELLO_SERVICE_KEY=sello_live_local_...
63
- SELLO_TOKEN_ISSUER_JWKS=https://auth.example.com/.well-known/jwks.json
64
- SELLO_LOG_URL=https://logs.example.com/api
65
- SELLO_SUBMIT_MODE=background
66
- ```
67
-
68
- Hosted `sello.build`:
69
-
70
- ```bash
71
- SELLO_SECRET_KEY=sello_test_...
72
- SELLO_SECRET_KEY=sello_live_...
73
- ```
74
-
75
- Hosted mode uses one server-side secret to fetch service config and enable local receipt signing by default. Managed remote signing must be a later explicit opt-in because it changes the trust model.
76
-
77
- ### Viewer Runtime Env
78
-
79
- Used by the owner CLI, local UI, or hosted dashboard to verify/decrypt actions.
80
-
81
- ```bash
82
- SELLO_OWNER_KEY=sello_owner_...
83
- SELLO_REGISTRY_URL=https://registry.example.com/sello.json
84
- SELLO_REGISTRY_SIGNATURE=...
85
- SELLO_REGISTRY_TRUST_ROOT_PUBLIC_KEY=...
86
- SELLO_LOG_URL=https://logs.example.com/api
87
- ```
88
-
89
- The owner key must not be required in the service process.
90
-
91
- ## Public API
92
-
93
- ```ts
94
- const receipts = sello.service();
95
- const receipts = sello.service("calendar.example.com/mcp/v1");
96
- const receipts = sello.service({ service, serviceKey, tokenIssuer, log, submit });
97
- ```
98
-
99
- ```ts
100
- const wrapped = receipts.tool(actionType, handler, options);
101
- await receipts.flush();
102
- ```
103
-
104
- Tool behavior:
105
-
106
- - Verify token before handler execution.
107
- - Emit `success`, `error`, or `denied` receipts.
108
- - Return handler response unchanged.
109
- - Rethrow handler errors.
110
- - Use canonical JSON hashing by default.
111
- - Submit in background by default.
112
- - Support `submit.mode: "await"` for strict durability.
113
- - Support explicit custom log adapters for self-hosting.
114
-
115
- ## Logged Actions UX
116
-
117
- ```bash
118
- npx sello actions --token <agent-token>
119
- ```
120
-
121
- Behavior:
122
-
123
- - Loads viewer config, not service config.
124
- - Computes `sello_token_ref`.
125
- - Queries trusted logs.
126
- - Verifies inclusion, service signature, revocation, HPKE decryption, and receipt body shape.
127
- - Prints verified actions and rejected receipts.
128
-
129
- Local dev:
130
-
131
- ```bash
132
- npx sello dev
133
- npx sello actions
134
- ```
135
-
136
- In dev mode, `sello dev` remembers the latest dev token and owner key in ignored local state so `npx sello actions` works without extra flags.
137
-
138
- Privacy rule:
139
-
140
- - Public logs store encrypted receipts.
141
- - Viewing action details requires the owner private key or delegated viewer key.
142
- - Self-hosted CLI decrypts locally.
143
- - Hosted dashboard must use client-side decryption or explicit delegated viewer keys.
144
-
145
- ## Phase Plan
146
-
147
- ### Phase 0: Baseline And SDK Contract
148
-
149
- - Write SDK examples into docs first.
150
- - Define env names, config precedence, and friendly errors.
151
- - Document service env versus viewer env.
152
- - Record deferred items: production Rekor proof verification, hosted dashboard, managed signing, durable queue.
153
- - Run `node --run test` and `node --run pack:check`.
154
- - Security audit: check the SDK contract does not weaken receiver-side signing or owner-side decryption.
155
-
156
- ### Phase 1: Env-First SDK Facade
157
-
158
- - Add `sello.service()`.
159
- - Add env config loader.
160
- - Add key normalization for `Uint8Array` and encoded string inputs.
161
- - Add explicit config override path.
162
- - Add friendly missing-config errors.
163
- - Tests: env loading, service id override, explicit config override, hosted config selection, no owner key required for service emission.
164
- - Security audit: check secret handling, env precedence, errors, logging, and hosted/self-hosted boundaries.
165
-
166
- ### Phase 2: Receipt Build/Submit Split And Background Publisher
167
-
168
- - Refactor receipt creation into build/encrypt/sign first, append second.
169
- - Keep existing `createReceipt()` behavior by composing build + append.
170
- - Add bounded background publisher with concurrency, `flush()`, `onSubmitError`, and `onDrop`.
171
- - Default to background submission.
172
- - Support `submit.mode: "await"`.
173
- - Tests: existing receipt tests, built envelope verification, background latency, `flush()`, overflow, failures, await mode, concurrency.
174
- - Security audit: check durability wording, queue bounds, memory pressure, failure handling, and unchanged cryptography.
175
-
176
- ### Phase 3: Tool Wrapper MVP
177
-
178
- - Implement `receipts.tool(actionType, handler, options)`.
179
- - Default token extraction, input hashing, output hashing, and error hashing.
180
- - Support custom token extraction and canonicalizers.
181
- - Preserve handler semantics exactly.
182
- - Tests: success, error, denied, invalid token, custom extraction, custom canonicalizers, unchanged response, MCP compatibility.
183
- - Security audit: check token verification ordering, plaintext leakage, and service identity binding.
184
-
185
- ### Phase 4: Logs And Action Viewing
186
-
187
- - Add `sello.logs.memory(url)` for local tests/dev.
188
- - Add `sello.logs.http(url, options?)` for self-hosted Sello-compatible log servers.
189
- - Add `npx sello actions --token <token>`.
190
- - Add local dev `/actions` page.
191
- - Action viewing uses owner-side verification and decryption.
192
- - Tests: memory log, HTTP append/query, CLI output, dev-mode token fallback, rejected reason codes, `/actions` states, no action details without owner/delegated key.
193
- - Security audit: check owner-side decryption, no plaintext in public logs, and safe rejected-receipt display.
194
-
195
- ### Phase 5: Docs Polish And First-Run Flow
196
-
197
- - Add README section: **Add Sello in a Few Lines**.
198
- - Add `docs/sdk-quickstart.md`.
199
- - Document self-hosted development, self-hosted production, `sello.build` development, and `sello.build` production.
200
- - Document action viewing, token requirement, and privacy model.
201
- - Keep advanced explicit config separate from quickstart.
202
- - Tests: `node --run test`, `node --run pack:check`, manual quickstart run, docs do not require `sello.build`.
203
- - Security audit: review README, quickstart, CLI help, and examples with the full plan in hand.
204
-
205
- ## Assumptions
206
-
207
- - MVP ships inside the current `sello` package.
208
- - One excellent generic tool wrapper beats many shallow adapters.
209
- - Testing is required for every phase before the next phase starts.
210
- - A security audit is required after every phase before the next phase starts.
211
- - Each auditor receives the full plan, current phase scope, deferred-item list, and threat model.
212
- - The service process emits receipts but does not need the owner private key.
213
- - Local/self-hosted usage is first-class.
214
- - `sello.build` is optional convenience, not a protocol requirement.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes