Skip to content

Commit cf6a7ba

Browse files
committed
Tighten docs and verify real key rotation
1 parent 36b41aa commit cf6a7ba

28 files changed

+529
-169
lines changed

.github/workflows/release.yml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'sdk-v*'
7+
- 'v*'
8+
release:
9+
types: [published]
10+
11+
jobs:
12+
release:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
id-token: write
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Setup Node
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: 20
25+
registry-url: https://registry.npmjs.org
26+
cache: npm
27+
cache-dependency-path: typescript-sdk/package-lock.json
28+
29+
- name: Setup Python
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: '3.12'
33+
34+
- name: Install root npm metadata
35+
run: npm install
36+
37+
- name: Install TypeScript dependencies
38+
working-directory: typescript-sdk
39+
run: npm ci
40+
41+
- name: TypeScript typecheck
42+
working-directory: typescript-sdk
43+
run: npm run typecheck
44+
45+
- name: TypeScript build
46+
working-directory: typescript-sdk
47+
run: npm run build
48+
49+
- name: TypeScript tests
50+
working-directory: typescript-sdk
51+
run: npm run test
52+
53+
- name: Install Python dependencies
54+
working-directory: python-sdk
55+
run: pip install -e '.[dev]'
56+
57+
- name: Python lint
58+
working-directory: python-sdk
59+
run: python -m ruff check .
60+
61+
- name: Python type check
62+
working-directory: python-sdk
63+
run: python -m mypy commandlayer
64+
65+
- name: Python tests
66+
working-directory: python-sdk
67+
run: python -m pytest tests/ -v
68+
69+
- name: Build npm package
70+
working-directory: typescript-sdk
71+
run: npm pack --dry-run
72+
73+
- name: Build Python package
74+
working-directory: python-sdk
75+
run: python -m build
76+
77+
- name: Validate Python package
78+
working-directory: python-sdk
79+
run: python -m twine check dist/*
80+
81+
- name: Publish npm
82+
if: github.event_name == 'push' || github.event_name == 'release'
83+
working-directory: typescript-sdk
84+
run: npm publish --access public
85+
env:
86+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
87+
88+
- name: Publish PyPI
89+
if: github.event_name == 'push' || github.event_name == 'release'
90+
working-directory: python-sdk
91+
run: python -m twine upload dist/*
92+
env:
93+
TWINE_USERNAME: __token__
94+
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}

CONTRIBUTING.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Contributing
2+
3+
## Repo structure
4+
5+
- `typescript-sdk/` — npm package, CLI, and runtime-facing verification code.
6+
- `python-sdk/` — PyPI package and Python verification code.
7+
- `runtime/tests/` — cross-SDK tests that execute against `typescript-sdk/dist`.
8+
- `test_vectors/` — shared fixtures for receipts, ENS cases, malformed inputs, and rotation cases.
9+
- root docs — public usage docs plus maintainer/release policy docs.
10+
11+
## Install dependencies
12+
13+
```bash
14+
npm install
15+
cd python-sdk && pip install -e '.[dev]'
16+
```
17+
18+
## Run TypeScript tests
19+
20+
```bash
21+
npm run build
22+
npm run test
23+
```
24+
25+
## Run Python tests
26+
27+
```bash
28+
cd python-sdk
29+
pytest
30+
```
31+
32+
## Run runtime tests without guessing about build order
33+
34+
```bash
35+
npm run test:full
36+
```
37+
38+
## `test_vectors/`
39+
40+
`test_vectors/` contains shared canonical receipts, ENS resolution cases, invalid signature cases, key rotation cases, and envelope-vs-receipt coverage used by both SDKs and the runtime tests.
41+
42+
## Pull requests
43+
44+
- keep changes scoped to the task,
45+
- update shared docs and fixtures when behavior changes,
46+
- run the relevant test commands before opening the PR,
47+
- describe user-visible behavior changes and release impact clearly.
48+
49+
## Release rules
50+
51+
Release process and publish requirements live in `RELEASE_GUIDE.md`.

EXAMPLES.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ const response = await client.explain({
124124

125125
```ts
126126
const response = await client.format({
127-
content: "a: 1\nb: 2",
127+
content: "a: 1
128+
b: 2",
128129
to: "table"
129130
});
130131
```
@@ -162,7 +163,8 @@ cleaned = client.clean(content=" test@example.com ", operations=["trim", "red
162163
converted = client.convert(content='{"a":1}', from_format="json", to_format="csv")
163164
description = client.describe(subject="receipt verification")
164165
explanation = client.explain(subject="receipt verification", style="step-by-step")
165-
formatted = client.format(content="a: 1\nb: 2", to="table")
166+
formatted = client.format(content="a: 1
167+
b: 2", to="table")
166168
parsed = client.parse(content='{ "a": 1 }', content_type="json", mode="strict")
167169
fetched = client.fetch(source="https://example.com", include_metadata=True)
168170
```
@@ -207,30 +209,36 @@ result = verify_receipt(
207209

208210
## 5. CLI examples
209211

212+
The CLI has two usage layers:
213+
- verb-specific commands such as `summarize` and `analyze` for the fast, common paths,
214+
- `call` for generic or less common verbs when you want to provide the raw JSON body yourself.
215+
210216
### Summarize
211217

212218
```bash
213-
commandlayer summarize \
214-
--content "CommandLayer defines semantic verbs." \
215-
--style bullet_points \
216-
--json
219+
commandlayer summarize --content "CommandLayer defines semantic verbs." --style bullet_points --json
217220
```
218221

219222
### Analyze
220223

221224
```bash
222-
commandlayer analyze \
223-
--content "Invoice total: $500" \
224-
--goal "detect finance intent" \
225-
--json
225+
commandlayer analyze --content "Invoice total: $500" --goal "detect finance intent" --json
226+
```
227+
228+
### Generic call
229+
230+
```bash
231+
commandlayer call --verb classify --body '{"content":"Contact support@example.com"}' --json
226232
```
227233

228234
### Verify a saved receipt
229235

236+
`commandlayer verify` accepts either:
237+
- a canonical receipt JSON object, or
238+
- a full response envelope JSON object with a top-level `receipt` field.
239+
230240
```bash
231-
commandlayer verify \
232-
--file receipt.json \
233-
--public-key "ed25519:BASE64_PUBLIC_KEY"
241+
commandlayer verify --file receipt.json --public-key "ed25519:BASE64_PUBLIC_KEY"
234242
```
235243

236244
## 6. Runtime override
Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Developer Experience Guide
1+
# Maintainer Guide
22

3-
This document is for maintainers and advanced integrators. Start with `README.md` or `QUICKSTART.md` if you are adopting the SDK.
3+
This document is for maintainers changing SDK internals, fixtures, CI, or release mechanics. It is not for application developers using the SDK in their own projects; use `README.md`, `QUICKSTART.md`, or the package READMEs instead.
44

55
## Product rules this repo now enforces
66

@@ -15,7 +15,7 @@ This document is for maintainers and advanced integrators. Start with `README.md
1515
- `python-sdk/`: PyPI package and Python verification helpers.
1616
- `test_vectors/`: shared receipt fixtures used across SDKs.
1717
- `runtime/tests/`: cross-SDK protocol checks run against the built TypeScript package.
18-
- root docs: public landing page, quickstart, examples, and release guide.
18+
- root docs: public landing page, quickstart, examples, contributor guide, versioning policy, and release guide.
1919

2020
## Shared protocol model
2121

@@ -40,8 +40,8 @@ Clients normalize runtime responses into:
4040

4141
```json
4242
{
43-
"receipt": { ...canonical signed receipt... },
44-
"runtime_metadata": { ...optional unsigned context... }
43+
"receipt": { "...": "canonical signed receipt" },
44+
"runtime_metadata": { "...": "optional unsigned context" }
4545
}
4646
```
4747

@@ -66,17 +66,31 @@ Both SDKs use the same verification contract:
6666
3. recompute `sha256`,
6767
4. compare against `metadata.proof.hash_sha256`,
6868
5. verify the Ed25519 signature over the UTF-8 hash string,
69-
6. optionally discover the signing key via ENS.
69+
6. resolve signer keys via ENS when an explicit key is not provided,
70+
7. when a receipt carries `kid`, prefer the matching `cl.sig.pub.<kid>` record so older receipts still verify after key rotation.
7071

7172
## CLI rules
7273

73-
The npm package owns the primary `commandlayer` CLI.
74+
The npm package owns the only supported `commandlayer` CLI. The Python package does not ship a CLI.
7475

7576
The CLI should remain:
7677
- installable with `npm install -g @commandlayer/sdk`,
7778
- aligned with SDK examples,
7879
- useful for CI smoke tests,
79-
- capable of verifying saved receipts.
80+
- capable of verifying saved receipts or full response envelopes.
81+
82+
## Test execution and ordering
83+
84+
`runtime/tests` import `typescript-sdk/dist/index.cjs`, so a fresh clone must build the TypeScript SDK before running runtime tests.
85+
86+
Use the root scripts to avoid hidden ordering requirements:
87+
88+
```bash
89+
npm install
90+
npm run test:full
91+
```
92+
93+
`npm run test:full` runs the TypeScript install/build/tests, then the runtime tests against the built output.
8094

8195
## Maintenance checklist
8296

@@ -85,4 +99,4 @@ When protocol versions change:
8599
2. update root docs and per-package READMEs,
86100
3. regenerate or update shared fixtures,
87101
4. run both SDK test suites plus `runtime/tests`,
88-
5. confirm release instructions in `DEPLOYMENT_GUIDE.md` still match reality.
102+
5. confirm release automation and `RELEASE_GUIDE.md` still match reality.

QUICKSTART.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ pip install commandlayer
1818

1919
### CLI
2020

21-
The CLI ships with the npm package:
21+
The CLI ships with the TypeScript/npm package only:
2222

2323
```bash
2424
npm install -g @commandlayer/sdk
2525
```
2626

27+
The Python SDK does not ship a CLI. Python users should use the TypeScript CLI or call the Python API directly.
28+
2729
## 2. Make your first call
2830

2931
### TypeScript
@@ -117,24 +119,22 @@ Use the same signer-discovery model in both SDKs:
117119
- agent ENS TXT: `cl.receipt.signer`
118120
- signer ENS TXT: `cl.sig.pub`
119121
- signer ENS TXT: `cl.sig.kid`
122+
- signer ENS TXT: `cl.sig.pub.<kid>` for older receipts after key rotation
120123

121124
## 5. Try the CLI
122125

123126
```bash
124-
commandlayer summarize \
125-
--content "CommandLayer makes agent execution verifiable." \
126-
--style bullet_points \
127-
--json
127+
commandlayer summarize --content "CommandLayer makes agent execution verifiable." --style bullet_points --json
128128
```
129129

130130
Save the returned JSON and verify it:
131131

132132
```bash
133-
commandlayer verify \
134-
--file receipt.json \
135-
--public-key "ed25519:BASE64_PUBLIC_KEY"
133+
commandlayer verify --file receipt.json --public-key "ed25519:BASE64_PUBLIC_KEY"
136134
```
137135

136+
`commandlayer verify` accepts either a canonical receipt JSON object or a full response envelope with a top-level `receipt` field. New integrations should pass the canonical receipt explicitly.
137+
138138
## 6. What is stable today?
139139

140140
Stable in this repo:
@@ -152,5 +152,6 @@ Not claimed as first-class SDK support here:
152152

153153
- More recipes: `EXAMPLES.md`
154154
- Package docs: `typescript-sdk/README.md`, `python-sdk/README.md`
155-
- Maintainer notes: `DEVELOPER_EXPERIENCE.md`
156-
- Release flow: `DEPLOYMENT_GUIDE.md`
155+
- Contributor workflow: `CONTRIBUTING.md`
156+
- Maintainer notes: `MAINTAINER_GUIDE.md`
157+
- Release flow: `RELEASE_GUIDE.md`

README.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ const result = await verifyReceipt(response.receipt, {
147147
ENS signer discovery resolves:
148148
1. `cl.receipt.signer` on the agent ENS name,
149149
2. `cl.sig.pub` on the signer ENS name,
150-
3. `cl.sig.kid` on the signer ENS name.
150+
3. `cl.sig.kid` on the signer ENS name,
151+
4. `cl.sig.pub.<kid>` on the signer ENS name when verifying an older receipt after key rotation.
151152

152153
## CLI
153154

@@ -158,13 +159,21 @@ commandlayer summarize --content "Test text" --style bullet_points --json
158159
commandlayer verify --file receipt.json --public-key "ed25519:BASE64_PUBLIC_KEY"
159160
```
160161

162+
The TypeScript SDK includes the `commandlayer` CLI. The Python SDK does not include a CLI.
163+
164+
Python users should either:
165+
- use the TypeScript CLI for smoke tests, demos, and CI workflows, or
166+
- use the Python API directly inside Python applications and scripts.
167+
161168
The CLI is intended for demos, CI smoke tests, debugging, and reproducing SDK flows without writing app code.
162169

163170
## Repo guide
164171

165172
- Fast onboarding: `QUICKSTART.md`
166173
- Cookbook examples: `EXAMPLES.md`
167-
- Maintainer / architecture notes: `DEVELOPER_EXPERIENCE.md`
168-
- Build, release, and publish flow: `DEPLOYMENT_GUIDE.md`
174+
- Contributor workflow: `CONTRIBUTING.md`
175+
- Maintainer / release operations: `MAINTAINER_GUIDE.md`
176+
- Build, release, and publish flow: `RELEASE_GUIDE.md`
177+
- Versioning policy: `VERSIONING.md`
169178
- TypeScript package docs: `typescript-sdk/README.md`
170179
- Python package docs: `python-sdk/README.md`

0 commit comments

Comments
 (0)