provenance-protocol 0.1.1 → 0.1.3

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # provenance-protocol
2
2
 
3
- SDK for querying the [Provenance](https://provenance.dev) agent identity index.
3
+ SDK for querying the [Provenance](https://getprovenance.dev) agent identity index.
4
4
 
5
5
  Drop this into any receiving system — marketplace, API, agent orchestrator —
6
6
  to verify an AI agent's identity and trust profile before allowing it in.
@@ -127,8 +127,88 @@ if (result.fallback) {
127
127
  | `incidents` | number | Number of open incidents |
128
128
  | `status` | string | active / suspended / removed |
129
129
  | `model` | object | `{ provider, model_id }` if declared |
130
+ | `public_key` | string\|null | Base64 Ed25519 public key, if registered |
131
+ | `identity_verified` | boolean | Cryptographic proof of key ownership confirmed |
132
+ | `ajp_endpoint` | string\|null | AJP job endpoint URL, if the agent accepts delegated jobs |
130
133
  | `first_seen` | string | ISO date of first public appearance |
131
134
 
132
135
  ---
133
136
 
134
- ## MIT License provenance.dev
137
+ ## Registering your own agent
138
+
139
+ ```js
140
+ import { Provenance } from 'provenance-protocol';
141
+ import { generateProvenanceKeyPair, signChallenge } from 'provenance-protocol/keygen';
142
+
143
+ const provenance = new Provenance();
144
+
145
+ // One-time: generate a keypair
146
+ const { publicKey, privateKey } = generateProvenanceKeyPair();
147
+ // Store privateKey as PROVENANCE_PRIVATE_KEY env var — never commit it
148
+
149
+ // Sign proof of key ownership for registration
150
+ const provenanceId = 'provenance:github:your-org/your-agent';
151
+ const signed_challenge = signChallenge(privateKey, provenanceId, 'REGISTER');
152
+
153
+ await provenance.register({
154
+ id: provenanceId,
155
+ url: 'https://github.com/your-org/your-agent',
156
+ name: 'Your Agent',
157
+ description: 'What it does',
158
+ capabilities: ['read:web', 'write:summaries'],
159
+ constraints: ['no:pii'],
160
+ public_key: publicKey,
161
+ signed_challenge, // proves you control the private key
162
+ });
163
+ // → { created: true, identity_verified: true, confidence: 1.0 }
164
+ ```
165
+
166
+ ## Revoking a compromised key
167
+
168
+ ```js
169
+ import { signRevocation } from 'provenance-protocol/keygen';
170
+
171
+ const signed_challenge = signRevocation(process.env.PROVENANCE_PRIVATE_KEY, provenanceId);
172
+
173
+ await fetch('https://getprovenance.dev/api/agents/revoke', {
174
+ method: 'POST',
175
+ headers: { 'Content-Type': 'application/json' },
176
+ body: JSON.stringify({ provenance_id: provenanceId, signed_challenge }),
177
+ });
178
+ // Then generate a new keypair and re-register
179
+ ```
180
+
181
+ ---
182
+
183
+ ## CLI
184
+
185
+ ```bash
186
+ npx provenance keygen
187
+ npx provenance register --id provenance:github:your-org/your-agent --url https://github.com/...
188
+ npx provenance status provenance:github:alice/my-agent
189
+ npx provenance validate PROVENANCE.yml
190
+ npx provenance revoke --id provenance:github:your-org/your-agent
191
+ ```
192
+
193
+ Full CLI reference: [getprovenance.dev/docs#cli](https://getprovenance.dev/docs#cli)
194
+
195
+ ---
196
+
197
+ ## Layers
198
+
199
+ `provenance-protocol` is the identity layer. Protocols that build on it:
200
+
201
+ | Package | Purpose |
202
+ |---|---|
203
+ | `provenance-protocol` | Agent identity, trust, and registration (this package) |
204
+ | [`ajp-protocol`](https://www.npmjs.com/package/ajp-protocol) | Agent Job Protocol — agent-to-agent job delegation |
205
+
206
+ ---
207
+
208
+ ## Full documentation
209
+
210
+ [getprovenance.dev/docs](https://getprovenance.dev/docs)
211
+
212
+ ---
213
+
214
+ ## MIT License — getprovenance.dev
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "provenance-protocol",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "SDK for querying the Provenance agent identity index",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -9,11 +9,17 @@
9
9
  ".": {
10
10
  "types": "./src/index.d.ts",
11
11
  "import": "./src/index.js"
12
+ },
13
+ "./keygen": {
14
+ "types": "./src/keygen.d.ts",
15
+ "import": "./src/keygen.js"
12
16
  }
13
17
  },
14
18
  "files": [
15
19
  "src/index.js",
16
20
  "src/index.d.ts",
21
+ "src/keygen.js",
22
+ "src/keygen.d.ts",
17
23
  "README.md"
18
24
  ],
19
25
  "keywords": [
@@ -29,7 +35,7 @@
29
35
  "type": "git",
30
36
  "url": "https://github.com/ilucky21c/provenance-protocol"
31
37
  },
32
- "homepage": "https://provenance.dev",
38
+ "homepage": "https://getprovenance.dev",
33
39
  "engines": {
34
40
  "node": ">=14.0.0"
35
41
  }
package/src/index.d.ts CHANGED
@@ -164,7 +164,17 @@ export interface RegisterProfile {
164
164
  model_id?: string;
165
165
  contact_url?: string;
166
166
  ajp_endpoint?: string;
167
+ /**
168
+ * Base64-encoded Ed25519 SPKI DER public key.
169
+ * When provided, signed_challenge is also required.
170
+ */
167
171
  public_key?: string;
172
+ /**
173
+ * Base64 Ed25519 signature of `${provenance_id}:REGISTER` using your private key.
174
+ * Required when public_key is provided — proves you control the key you're registering.
175
+ * Generate with: signChallenge(privateKey, provenanceId, 'REGISTER') from provenance-protocol/keygen
176
+ */
177
+ signed_challenge?: string;
168
178
  version?: string;
169
179
  }
170
180
 
package/src/index.js CHANGED
@@ -44,7 +44,7 @@ async function _verifyEd25519(publicKeyBase64, signatureBase64, message) {
44
44
  return subtle.verify('Ed25519', cryptoKey, sigBuffer, msgBuffer);
45
45
  }
46
46
 
47
- const DEFAULT_API = 'https://provenance.dev';
47
+ const DEFAULT_API = 'https://getprovenance.dev';
48
48
  const DEFAULT_CACHE_TTL = 300; // 5 minutes
49
49
 
50
50
  // Simple LRU cache
@@ -100,9 +100,10 @@ export class Provenance {
100
100
  * const trust = await provenance.check('provenance:github:alice/research-assistant');
101
101
  * // {
102
102
  * // found: true,
103
- * // declared: true, — has PROVENANCE.yml
104
- * // age_days: 142, how long this agent has existed publicly
105
- * // confidence: 0.9,
103
+ * // declared: true, — has PROVENANCE.yml
104
+ * // identity_verified: true, cryptographic proof of ownership
105
+ * // age_days: 142, — how long this agent has existed publicly
106
+ * // confidence: 0.9, — internal signal, use declared/identity_verified for trust decisions
106
107
  * // capabilities: ['read:web', 'write:summaries'],
107
108
  * // constraints: ['no:financial:transact', 'no:pii'],
108
109
  * // incidents: 0,
@@ -132,6 +133,7 @@ export class Provenance {
132
133
  platform: data.platform,
133
134
  name: data.name,
134
135
  declared: data.declared,
136
+ identity_verified: data.identity_verified || false,
135
137
  confidence: data.confidence,
136
138
  age_days: data.timestamps?.first_seen
137
139
  ? Math.floor((Date.now() - new Date(data.timestamps.first_seen)) / 86400000)
@@ -510,7 +512,6 @@ export class Provenance {
510
512
  // → github/alice/research-assistant
511
513
  return provenanceId.replace('provenance:', '').replace(':', '/');
512
514
  }
513
- }
514
515
 
515
516
  // ── Self-registration ─────────────────────────────────────────────────────
516
517
 
@@ -518,30 +519,28 @@ export class Provenance {
518
519
  * Register or update this agent in the Provenance index.
519
520
  * Call once at agent startup — idempotent, safe to call on every boot.
520
521
  *
521
- * Example:
522
- * import { provenance } from 'provenance-protocol';
523
- *
524
- * await provenance.register({
525
- * id: 'provenance:github:your-org/your-agent',
526
- * url: 'https://github.com/your-org/your-agent',
527
- * name: 'Your Agent',
528
- * description: 'What it does',
529
- * capabilities: ['read:web', 'write:summaries'],
530
- * constraints: ['no:pii', 'no:financial:transact'],
531
- * });
522
+ * To register with cryptographic proof (identity_verified: true, confidence: 1.0),
523
+ * provide public_key and signed_challenge:
524
+ * import { signChallenge } from 'provenance-protocol/keygen';
525
+ * const signed_challenge = signChallenge(process.env.PROVENANCE_PRIVATE_KEY, id, 'REGISTER');
532
526
  *
533
527
  * @param {object} profile
534
- * @param {string} profile.id provenance:<platform>:<owner>/<name>
535
- * @param {string} profile.url Canonical URL (GitHub repo, package page, etc.)
536
- * @param {string} [profile.name] Display name
537
- * @param {string} [profile.description] One-sentence description
528
+ * @param {string} profile.id provenance:<platform>:<owner>/<name>
529
+ * Platforms: github, huggingface, npm, pypi, clawmarket, custom
530
+ * Use "custom" for private agents without a public repo.
531
+ * @param {string} [profile.url] Canonical URL. Optional for custom platform agents.
532
+ * @param {string} [profile.readme_summary] 2-3 sentence plain-English description shown on profile.
533
+ * For private agents without a README — write it yourself.
534
+ * @param {string} [profile.name] Display name
535
+ * @param {string} [profile.description] One-sentence description
538
536
  * @param {string[]} [profile.capabilities]
539
537
  * @param {string[]} [profile.constraints]
540
538
  * @param {string} [profile.model_provider]
541
539
  * @param {string} [profile.model_id]
542
540
  * @param {string} [profile.contact_url]
543
541
  * @param {string} [profile.ajp_endpoint]
544
- * @param {string} [profile.public_key] Ed25519 public key: "ed25519:<base64>"
542
+ * @param {string} [profile.public_key] Ed25519 SPKI DER public key (base64)
543
+ * @param {string} [profile.signed_challenge] Signature of `${id}:REGISTER` — required with public_key
545
544
  * @param {string} [profile.version]
546
545
  * @returns {{ created: boolean, updated: boolean, agent: object }}
547
546
  */
@@ -0,0 +1,48 @@
1
+ /**
2
+ * provenance-protocol — Key generation and signing utilities (TypeScript definitions)
3
+ * Node.js only. Not for browser use.
4
+ */
5
+
6
+ export interface KeyPair {
7
+ /** Base64-encoded SPKI DER public key. Put this in PROVENANCE.yml identity.public_key */
8
+ publicKey: string;
9
+ /** Base64-encoded PKCS8 DER private key. Store as PROVENANCE_PRIVATE_KEY env var. Never commit. */
10
+ privateKey: string;
11
+ }
12
+
13
+ /**
14
+ * Generate a new Ed25519 keypair for Provenance identity.
15
+ * Run once during agent setup.
16
+ */
17
+ export function generateProvenanceKeyPair(): KeyPair;
18
+
19
+ /**
20
+ * Sign a challenge nonce from a receiving system.
21
+ * Returns a base64-encoded signature over `${provenanceId}:${nonce}`.
22
+ *
23
+ * @param privateKeyBase64 Your PROVENANCE_PRIVATE_KEY (base64 PKCS8 DER)
24
+ * @param provenanceId Your agent's Provenance ID
25
+ * @param nonce The nonce sent by the receiving system
26
+ */
27
+ export function signChallenge(privateKeyBase64: string, provenanceId: string, nonce: string): string;
28
+
29
+ /**
30
+ * Sign your PROVENANCE.yml identity claim.
31
+ *
32
+ * Produces the `identity.signature` value for PROVENANCE.yml.
33
+ * Signs `${provenanceId}:${publicKeyBase64}` — binding the keypair to your specific agent ID.
34
+ * Run once during setup, after generateProvenanceKeyPair().
35
+ *
36
+ * @param privateKeyBase64 Your PROVENANCE_PRIVATE_KEY (base64 PKCS8 DER)
37
+ * @param provenanceId Your agent's Provenance ID
38
+ * @param publicKeyBase64 The public key you generated (base64 SPKI DER)
39
+ * @returns Base64 signature — put in PROVENANCE.yml identity.signature
40
+ */
41
+ export function signForProvenance(privateKeyBase64: string, provenanceId: string, publicKeyBase64: string): string;
42
+
43
+ /**
44
+ * Sign a revocation request — clears your agent's public key and identity_verified status.
45
+ * Use when your private key is compromised or you're rotating keys.
46
+ * Send the result as signed_challenge to POST /api/agents/revoke.
47
+ */
48
+ export function signRevocation(privateKeyBase64: string, provenanceId: string): string;
package/src/keygen.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * provenance-protocol — Key generation and signing utilities
3
+ *
4
+ * Agent operators use this to:
5
+ * 1. Generate an Ed25519 keypair once (setup)
6
+ * 2. Put the public key in PROVENANCE.yml under identity.public_key
7
+ * 3. Keep the private key in their environment (never committed, never shared)
8
+ * 4. Sign challenges from receiving systems at runtime
9
+ *
10
+ * Usage (one-time setup):
11
+ * import { generateProvenanceKeyPair } from 'provenance-protocol/keygen';
12
+ * const { publicKey, privateKey } = generateProvenanceKeyPair();
13
+ * // Add publicKey to your PROVENANCE.yml:
14
+ * // identity:
15
+ * // public_key: "<publicKey>"
16
+ * // Store privateKey as an environment variable: PROVENANCE_PRIVATE_KEY=<privateKey>
17
+ *
18
+ * Usage (runtime — signing challenges):
19
+ * import { signChallenge } from 'provenance-protocol/keygen';
20
+ * const signature = signChallenge(process.env.PROVENANCE_PRIVATE_KEY, provenanceId, nonce);
21
+ * // Return signature to the receiving system
22
+ *
23
+ * Note: This module uses Node.js built-in crypto. It is Node-only (not browser).
24
+ * The verification side (in index.js) uses Web Crypto and works everywhere.
25
+ */
26
+
27
+ import { generateKeyPairSync, sign, createPrivateKey } from 'crypto';
28
+
29
+ /**
30
+ * Generate a new Ed25519 keypair for use with Provenance identity.
31
+ *
32
+ * Run this once during agent setup. Add the public key to PROVENANCE.yml.
33
+ * Store the private key securely as an environment variable.
34
+ *
35
+ * @returns {{ publicKey: string, privateKey: string }}
36
+ * publicKey — base64-encoded SPKI DER. Goes in PROVENANCE.yml identity.public_key
37
+ * privateKey — base64-encoded PKCS8 DER. Store as PROVENANCE_PRIVATE_KEY env var
38
+ *
39
+ * Example:
40
+ * const { publicKey, privateKey } = generateProvenanceKeyPair();
41
+ * console.log('Add to PROVENANCE.yml:');
42
+ * console.log('identity:');
43
+ * console.log(` public_key: "${publicKey}"`);
44
+ * console.log('\nStore as environment variable:');
45
+ * console.log(`PROVENANCE_PRIVATE_KEY=${privateKey}`);
46
+ */
47
+ export function generateProvenanceKeyPair() {
48
+ const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
49
+ publicKeyEncoding: { type: 'spki', format: 'der' },
50
+ privateKeyEncoding: { type: 'pkcs8', format: 'der' },
51
+ });
52
+
53
+ return {
54
+ publicKey: Buffer.from(publicKey).toString('base64'),
55
+ privateKey: Buffer.from(privateKey).toString('base64'),
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Sign a challenge from a receiving system.
61
+ *
62
+ * Call this when a receiving system sends you a nonce to prove your identity.
63
+ * The signed message is always `${provenanceId}:${nonce}` — this binds the
64
+ * signature to your specific identity and prevents replay attacks.
65
+ *
66
+ * @param {string} privateKeyBase64 Your PROVENANCE_PRIVATE_KEY (base64 PKCS8 DER)
67
+ * @param {string} provenanceId Your provenance ID, e.g. "provenance:github:alice/agent"
68
+ * @param {string} nonce The nonce sent by the receiving system
69
+ * @returns {string} Base64-encoded signature to return to the receiver
70
+ *
71
+ * Example:
72
+ * app.post('/prove-identity', (req, res) => {
73
+ * const { provenanceId, nonce } = req.body;
74
+ * const signature = signChallenge(
75
+ * process.env.PROVENANCE_PRIVATE_KEY,
76
+ * provenanceId,
77
+ * nonce
78
+ * );
79
+ * res.json({ signature });
80
+ * });
81
+ */
82
+ export function signChallenge(privateKeyBase64, provenanceId, nonce) {
83
+ const keyBuffer = Buffer.from(privateKeyBase64, 'base64');
84
+ const privateKey = createPrivateKey({ key: keyBuffer, format: 'der', type: 'pkcs8' });
85
+ const message = Buffer.from(`${provenanceId}:${nonce}`, 'utf8');
86
+ return sign(null, message, privateKey).toString('base64');
87
+ }
88
+
89
+ /**
90
+ * Sign your PROVENANCE.yml identity claim.
91
+ *
92
+ * Call this once after generating your keypair to produce the `identity.signature`
93
+ * value that goes into PROVENANCE.yml. The signature proves you control the private
94
+ * key that matches the public key in the file.
95
+ *
96
+ * The signed message is `${provenanceId}:${publicKeyBase64}` — this binds the key
97
+ * pair to your specific Provenance ID, preventing key reuse across identities.
98
+ *
99
+ * @param {string} privateKeyBase64 Your PROVENANCE_PRIVATE_KEY (base64 PKCS8 DER)
100
+ * @param {string} provenanceId Your agent's Provenance ID, e.g. "provenance:github:alice/agent"
101
+ * @param {string} publicKeyBase64 The public key you're registering (base64 SPKI DER)
102
+ * @returns {string} Base64-encoded signature — put this in identity.signature
103
+ *
104
+ * Example (one-time setup):
105
+ * import { generateProvenanceKeyPair, signForProvenance } from 'provenance-protocol/keygen';
106
+ * const { publicKey, privateKey } = generateProvenanceKeyPair();
107
+ * const id = 'provenance:github:your-org/your-agent';
108
+ * const signature = signForProvenance(privateKey, id, publicKey);
109
+ * console.log('Add to PROVENANCE.yml:');
110
+ * console.log('identity:');
111
+ * console.log(` public_key: "${publicKey}"`);
112
+ * console.log(` signature: "${signature}"`);
113
+ */
114
+ /**
115
+ * Sign a revocation request.
116
+ *
117
+ * Call this when you want to revoke your agent's cryptographic identity —
118
+ * e.g. if your private key was compromised or you're rotating keys.
119
+ *
120
+ * @param {string} privateKeyBase64 Your current PROVENANCE_PRIVATE_KEY
121
+ * @param {string} provenanceId Your agent's Provenance ID
122
+ * @returns {string} Base64 signature — send as signed_challenge to POST /api/agents/revoke
123
+ *
124
+ * Example:
125
+ * import { signRevocation } from 'provenance-protocol/keygen';
126
+ * const signed_challenge = signRevocation(process.env.PROVENANCE_PRIVATE_KEY, provenanceId);
127
+ * await fetch('https://getprovenance.dev/api/agents/revoke', {
128
+ * method: 'POST',
129
+ * headers: { 'Content-Type': 'application/json' },
130
+ * body: JSON.stringify({ provenance_id: provenanceId, signed_challenge }),
131
+ * });
132
+ */
133
+ export function signRevocation(privateKeyBase64, provenanceId) {
134
+ return signChallenge(privateKeyBase64, provenanceId, 'REVOKE');
135
+ }
136
+
137
+ export function signForProvenance(privateKeyBase64, provenanceId, publicKeyBase64) {
138
+ const keyBuffer = Buffer.from(privateKeyBase64, 'base64');
139
+ const privateKey = createPrivateKey({ key: keyBuffer, format: 'der', type: 'pkcs8' });
140
+ const message = Buffer.from(`${provenanceId}:${publicKeyBase64}`, 'utf8');
141
+ return sign(null, message, privateKey).toString('base64');
142
+ }