@imagxp/protocol 1.0.0 → 1.0.2

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/dist/agent.js CHANGED
@@ -1,4 +1,4 @@
1
- import { generateKeyPair, signData, exportPublicKey } from './crypto.js';
1
+ import { generateKeyPair, signData, exportPublicKey, importPrivateKey, importPublicKey } from './crypto.js';
2
2
  import { IMAGXP_VERSION } from './constants.js';
3
3
  export class IMAGXPAgent {
4
4
  constructor() {
@@ -10,9 +10,24 @@ export class IMAGXPAgent {
10
10
  * @param customAgentId For PRODUCTION, this should be your domain (e.g., "bot.openai.com")
11
11
  */
12
12
  async initialize(customAgentId) {
13
- this.keyPair = await generateKeyPair();
13
+ if (process.env.IMAGXP_PRIVATE_KEY && process.env.IMAGXP_PUBLIC_KEY) {
14
+ // 1. Load Persistent Identity from Environment
15
+ console.log(`[IMAGXP] Loading Agent Identity from Environment...`);
16
+ try {
17
+ const privateKey = await importPrivateKey(process.env.IMAGXP_PRIVATE_KEY);
18
+ const publicKey = await importPublicKey(process.env.IMAGXP_PUBLIC_KEY);
19
+ this.keyPair = { privateKey, publicKey };
20
+ }
21
+ catch (e) {
22
+ console.error("Failed to load keys from env:", e);
23
+ }
24
+ }
25
+ // Fallback or Normal Init
26
+ if (!this.keyPair) {
27
+ this.keyPair = await generateKeyPair();
28
+ }
14
29
  // Use the provided ID (authentic) or generate a session ID (ephemeral)
15
- this.agentId = customAgentId || "agent_" + Math.random().toString(36).substring(7);
30
+ this.agentId = process.env.IMAGXP_AGENT_ID || customAgentId || "agent_" + Math.random().toString(36).substring(7);
16
31
  }
17
32
  async createAccessRequest(resource, purpose, options = {}) {
18
33
  if (!this.keyPair)
package/dist/crypto.d.ts CHANGED
@@ -7,3 +7,5 @@ export declare function signData(privateKey: CryptoKey, data: string): Promise<s
7
7
  export declare function verifySignature(publicKey: CryptoKey, data: string, signatureHex: string): Promise<boolean>;
8
8
  export declare function exportPublicKey(key: CryptoKey): Promise<string>;
9
9
  export declare function importPublicKey(keyData: string): Promise<CryptoKey>;
10
+ export declare function exportPrivateKey(key: CryptoKey): Promise<string>;
11
+ export declare function importPrivateKey(keyData: string): Promise<CryptoKey>;
package/dist/crypto.js CHANGED
@@ -33,6 +33,18 @@ export async function importPublicKey(keyData) {
33
33
  }
34
34
  return await crypto.subtle.importKey("spki", bytes, { name: "ECDSA", namedCurve: "P-256" }, true, ["verify"]);
35
35
  }
36
+ export async function exportPrivateKey(key) {
37
+ const exported = await crypto.subtle.exportKey("pkcs8", key);
38
+ return btoa(String.fromCharCode(...new Uint8Array(exported)));
39
+ }
40
+ export async function importPrivateKey(keyData) {
41
+ const binaryString = atob(keyData);
42
+ const bytes = new Uint8Array(binaryString.length);
43
+ for (let i = 0; i < binaryString.length; i++) {
44
+ bytes[i] = binaryString.charCodeAt(i);
45
+ }
46
+ return await crypto.subtle.importKey("pkcs8", bytes, { name: "ECDSA", namedCurve: "P-256" }, true, ["sign"]);
47
+ }
36
48
  // Helpers
37
49
  function bufToHex(buffer) {
38
50
  return Array.from(new Uint8Array(buffer))
package/dist/express.js CHANGED
@@ -4,14 +4,28 @@
4
4
  */
5
5
  import { IMAGXPPublisher } from './publisher.js';
6
6
  import { ContentOrigin } from './types.js';
7
- import { generateKeyPair } from './crypto.js';
7
+ import { generateKeyPair, importPrivateKey, importPublicKey } from './crypto.js';
8
8
  export class IMAGXP {
9
9
  constructor(config) {
10
10
  this.publisher = new IMAGXPPublisher({ version: '1.1', ...config.policy }, config.strategy || 'PASSIVE', config.cache);
11
11
  this.origin = ContentOrigin[config.meta.origin];
12
- this.ready = generateKeyPair().then(keys => {
13
- return this.publisher.initialize(keys);
14
- });
12
+ const publisher = this.publisher;
13
+ this.ready = (async () => {
14
+ let keys = null;
15
+ if (process.env.IMAGXP_PRIVATE_KEY && process.env.IMAGXP_PUBLIC_KEY) {
16
+ try {
17
+ const privateKey = await importPrivateKey(process.env.IMAGXP_PRIVATE_KEY);
18
+ const publicKey = await importPublicKey(process.env.IMAGXP_PUBLIC_KEY);
19
+ keys = { privateKey, publicKey };
20
+ }
21
+ catch (e) {
22
+ console.error("IMAGXP: Failed to load keys from env", e);
23
+ }
24
+ }
25
+ if (!keys)
26
+ keys = await generateKeyPair();
27
+ await publisher.initialize(keys);
28
+ })();
15
29
  }
16
30
  static init(config) {
17
31
  return new IMAGXP(config);
package/dist/nextjs.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { IMAGXPPublisher } from './publisher.js';
6
6
  import { ContentOrigin } from './types.js';
7
- import { generateKeyPair } from './crypto.js';
7
+ import { generateKeyPair, importPrivateKey, importPublicKey } from './crypto.js';
8
8
  const createJsonResponse = (body, status = 200) => {
9
9
  return new Response(JSON.stringify(body), {
10
10
  status,
@@ -15,7 +15,23 @@ export class IMAGXPNext {
15
15
  constructor(config) {
16
16
  this.publisher = new IMAGXPPublisher({ version: '1.1', ...config.policy }, config.strategy || 'PASSIVE', config.cache);
17
17
  this.origin = ContentOrigin[config.meta.origin];
18
- this.ready = generateKeyPair().then(keys => this.publisher.initialize(keys));
18
+ const publisher = this.publisher;
19
+ this.ready = (async () => {
20
+ let keys = null;
21
+ if (process.env.IMAGXP_PRIVATE_KEY && process.env.IMAGXP_PUBLIC_KEY) {
22
+ try {
23
+ const privateKey = await importPrivateKey(process.env.IMAGXP_PRIVATE_KEY);
24
+ const publicKey = await importPublicKey(process.env.IMAGXP_PUBLIC_KEY);
25
+ keys = { privateKey, publicKey };
26
+ }
27
+ catch (e) {
28
+ console.error("IMAGXP: Failed to load keys from env", e);
29
+ }
30
+ }
31
+ if (!keys)
32
+ keys = await generateKeyPair();
33
+ await publisher.initialize(keys);
34
+ })();
19
35
  }
20
36
  static init(config) {
21
37
  return new IMAGXPNext(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imagxp/protocol",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "TypeScript reference implementation of IMAGXP v1.1",
5
5
  "keywords": [
6
6
  "imagxp",
@@ -37,6 +37,10 @@
37
37
  "type": "git",
38
38
  "url": "https://github.com/imagxp-protocol/imagxp.git"
39
39
  },
40
+ "homepage": "https://imagxp.com",
41
+ "bugs": {
42
+ "url": "https://github.com/imagxp-protocol/imagxp/issues"
43
+ },
40
44
  "publishConfig": {
41
45
  "access": "public"
42
46
  },
@@ -50,4 +54,4 @@
50
54
  "jose": "^6.1.3",
51
55
  "node-fetch": "^2.7.0"
52
56
  }
53
- }
57
+ }
package/src/agent.ts CHANGED
@@ -2,9 +2,11 @@
2
2
  * Layer 2: Agent SDK
3
3
  */
4
4
  import { AccessPurpose, ProtocolHeader, SignedAccessRequest, FeedbackSignal, QualityFlag, AgentIdentityManifest } from './types.js';
5
- import { generateKeyPair, signData, exportPublicKey } from './crypto.js';
5
+ import { generateKeyPair, signData, exportPublicKey, importPrivateKey, importPublicKey } from './crypto.js';
6
6
  import { IMAGXP_VERSION } from './constants.js';
7
7
 
8
+ declare const process: any;
9
+
8
10
  export interface AccessOptions {
9
11
  adsDisplayed?: boolean;
10
12
  }
@@ -18,9 +20,25 @@ export class IMAGXPAgent {
18
20
  * @param customAgentId For PRODUCTION, this should be your domain (e.g., "bot.openai.com")
19
21
  */
20
22
  async initialize(customAgentId?: string) {
21
- this.keyPair = await generateKeyPair();
23
+ if (process.env.IMAGXP_PRIVATE_KEY && process.env.IMAGXP_PUBLIC_KEY) {
24
+ // 1. Load Persistent Identity from Environment
25
+ console.log(`[IMAGXP] Loading Agent Identity from Environment...`);
26
+ try {
27
+ const privateKey = await importPrivateKey(process.env.IMAGXP_PRIVATE_KEY);
28
+ const publicKey = await importPublicKey(process.env.IMAGXP_PUBLIC_KEY);
29
+ this.keyPair = { privateKey, publicKey };
30
+ } catch (e) {
31
+ console.error("Failed to load keys from env:", e);
32
+ }
33
+ }
34
+
35
+ // Fallback or Normal Init
36
+ if (!this.keyPair) {
37
+ this.keyPair = await generateKeyPair();
38
+ }
39
+
22
40
  // Use the provided ID (authentic) or generate a session ID (ephemeral)
23
- this.agentId = customAgentId || "agent_" + Math.random().toString(36).substring(7);
41
+ this.agentId = process.env.IMAGXP_AGENT_ID || customAgentId || "agent_" + Math.random().toString(36).substring(7);
24
42
  }
25
43
 
26
44
  async createAccessRequest(
package/src/crypto.ts CHANGED
@@ -62,6 +62,27 @@ export async function importPublicKey(keyData: string): Promise<CryptoKey> {
62
62
  );
63
63
  }
64
64
 
65
+ export async function exportPrivateKey(key: CryptoKey): Promise<string> {
66
+ const exported = await crypto.subtle.exportKey("pkcs8", key);
67
+ return btoa(String.fromCharCode(...new Uint8Array(exported)));
68
+ }
69
+
70
+ export async function importPrivateKey(keyData: string): Promise<CryptoKey> {
71
+ const binaryString = atob(keyData);
72
+ const bytes = new Uint8Array(binaryString.length);
73
+ for (let i = 0; i < binaryString.length; i++) {
74
+ bytes[i] = binaryString.charCodeAt(i);
75
+ }
76
+
77
+ return await crypto.subtle.importKey(
78
+ "pkcs8",
79
+ bytes,
80
+ { name: "ECDSA", namedCurve: "P-256" },
81
+ true,
82
+ ["sign"]
83
+ );
84
+ }
85
+
65
86
  // Helpers
66
87
  function bufToHex(buffer: ArrayBuffer): string {
67
88
  return Array.from(new Uint8Array(buffer))
package/src/express.ts CHANGED
@@ -4,7 +4,9 @@
4
4
  */
5
5
  import { IMAGXPPublisher } from './publisher.js';
6
6
  import { AccessPolicy, ContentOrigin, UnauthenticatedStrategy, IdentityCache } from './types.js';
7
- import { generateKeyPair } from './crypto.js';
7
+ import { generateKeyPair, importPrivateKey, importPublicKey } from './crypto.js';
8
+
9
+ declare const process: any;
8
10
 
9
11
  export interface IMAGXPConfig {
10
12
  policy: Omit<AccessPolicy, 'version'>;
@@ -31,9 +33,19 @@ export class IMAGXP {
31
33
 
32
34
  this.origin = ContentOrigin[config.meta.origin];
33
35
 
34
- this.ready = generateKeyPair().then(keys => {
35
- return this.publisher.initialize(keys);
36
- });
36
+ const publisher = this.publisher;
37
+ this.ready = (async () => {
38
+ let keys: CryptoKeyPair | null = null;
39
+ if (process.env.IMAGXP_PRIVATE_KEY && process.env.IMAGXP_PUBLIC_KEY) {
40
+ try {
41
+ const privateKey = await importPrivateKey(process.env.IMAGXP_PRIVATE_KEY);
42
+ const publicKey = await importPublicKey(process.env.IMAGXP_PUBLIC_KEY);
43
+ keys = { privateKey, publicKey };
44
+ } catch (e) { console.error("IMAGXP: Failed to load keys from env", e); }
45
+ }
46
+ if (!keys) keys = await generateKeyPair();
47
+ await publisher.initialize(keys);
48
+ })();
37
49
  }
38
50
 
39
51
  static init(config: IMAGXPConfig): IMAGXP {
package/src/nextjs.ts CHANGED
@@ -4,7 +4,9 @@
4
4
  */
5
5
  import { IMAGXPPublisher } from './publisher.js';
6
6
  import { AccessPolicy, ContentOrigin, UnauthenticatedStrategy, IdentityCache } from './types.js';
7
- import { generateKeyPair } from './crypto.js';
7
+ import { generateKeyPair, importPrivateKey, importPublicKey } from './crypto.js';
8
+
9
+ declare const process: any;
8
10
 
9
11
  type NextRequest = any;
10
12
  type NextResponse = any;
@@ -39,7 +41,20 @@ export class IMAGXPNext {
39
41
  config.cache
40
42
  );
41
43
  this.origin = ContentOrigin[config.meta.origin];
42
- this.ready = generateKeyPair().then(keys => this.publisher.initialize(keys));
44
+
45
+ const publisher = this.publisher;
46
+ this.ready = (async () => {
47
+ let keys: CryptoKeyPair | null = null;
48
+ if (process.env.IMAGXP_PRIVATE_KEY && process.env.IMAGXP_PUBLIC_KEY) {
49
+ try {
50
+ const privateKey = await importPrivateKey(process.env.IMAGXP_PRIVATE_KEY);
51
+ const publicKey = await importPublicKey(process.env.IMAGXP_PUBLIC_KEY);
52
+ keys = { privateKey, publicKey };
53
+ } catch (e) { console.error("IMAGXP: Failed to load keys from env", e); }
54
+ }
55
+ if (!keys) keys = await generateKeyPair();
56
+ await publisher.initialize(keys);
57
+ })();
43
58
  }
44
59
 
45
60
  static init(config: IMAGXPConfig): IMAGXPNext {