@agfpd/iapeer 0.2.76 → 0.2.77

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agfpd/iapeer",
3
- "version": "0.2.76",
3
+ "version": "0.2.77",
4
4
  "description": "Foundation core for the iapeer multi-agent ecosystem: identity, registry, storage, codec.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/init/index.ts CHANGED
@@ -75,8 +75,15 @@ interface McpHttpServer {
75
75
  * Idempotently wire the foundation HTTP-MCP server into the peer's project-scope
76
76
  * `<cwd>/.mcp.json` (claude-specific). MERGE, not clobber: existing mcpServers are
77
77
  * preserved; only the `iapeer` entry is (re)written. The X-IAPeer-Identity header
78
- * carries `claude-<personality>` so the daemon resolves the caller per request. The
79
- * caller is authenticated by that header (the same proof live-verified at cold-start).
78
+ * carries `${PEER_IDENTITY:-claude-<personality>}`: claude expands it from the session
79
+ * env PEER_IDENTITY (set by the launch — invocation.ts), so the caller identity follows
80
+ * the SESSION, not the cwd file. This closes a cross-identity bug — a peer that `cd`s into
81
+ * ANOTHER peer's project dir + reloads used to pick up THAT dir's `.mcp.json` identity
82
+ * literal and assume its identity (the daemon trusts the header). With env-expansion the
83
+ * value resolves from the reader's own session env regardless of which `.mcp.json` is read.
84
+ * The `:-claude-<personality>` fallback keeps a manually-launched session (no PEER_IDENTITY
85
+ * env) from failing config parse — it resolves to this peer's own literal, correct in its
86
+ * OWN dir. The daemon resolves the caller per request from this header.
80
87
  * Returns the written path. Re-running init is a no-op-equivalent (same bytes).
81
88
  */
82
89
  export function writeClaudeMcpConfig(cwd: string, personality: string, daemonUrl: string): string {
@@ -100,7 +107,7 @@ export function writeClaudeMcpConfig(cwd: string, personality: string, daemonUrl
100
107
  const server: McpHttpServer = {
101
108
  type: 'http',
102
109
  url: daemonUrl,
103
- headers: { 'X-IAPeer-Identity': `claude-${personality}` },
110
+ headers: { 'X-IAPeer-Identity': `\${PEER_IDENTITY:-claude-${personality}}` },
104
111
  }
105
112
  doc.mcpServers = { ...(doc.mcpServers ?? {}), [IAPEER_MCP_SERVER_NAME]: server }
106
113
  writeFileAtomic(path, `${JSON.stringify(doc, null, 2)}\n`, 0o644)
@@ -58,7 +58,9 @@ describe('writeClaudeMcpConfig', () => {
58
58
  expect(doc.mcpServers[IAPEER_MCP_SERVER_NAME]).toEqual({
59
59
  type: 'http',
60
60
  url: 'http://127.0.0.1:8765/mcp',
61
- headers: { 'X-IAPeer-Identity': 'claude-boris' },
61
+ // env-expanded by claude from the session PEER_IDENTITY; literal fallback for
62
+ // a manual (no-env) session — identity follows the SESSION, not the cwd file.
63
+ headers: { 'X-IAPeer-Identity': '${PEER_IDENTITY:-claude-boris}' },
62
64
  })
63
65
  })
64
66
  test('MERGES — preserves other mcpServers, only (re)writes iapeer', () => {
@@ -66,7 +68,7 @@ describe('writeClaudeMcpConfig', () => {
66
68
  writeClaudeMcpConfig(cwd, 'boris', 'http://127.0.0.1:8765/mcp')
67
69
  const doc = JSON.parse(readFileSync(join(cwd, '.mcp.json'), 'utf8'))
68
70
  expect(doc.mcpServers.other).toEqual({ type: 'http', url: 'https://x/mcp' })
69
- expect(doc.mcpServers.iapeer.headers['X-IAPeer-Identity']).toBe('claude-boris')
71
+ expect(doc.mcpServers.iapeer.headers['X-IAPeer-Identity']).toBe('${PEER_IDENTITY:-claude-boris}')
70
72
  })
71
73
  test('idempotent — re-running yields the same bytes', () => {
72
74
  const p = writeClaudeMcpConfig(cwd, 'boris', 'http://127.0.0.1:8765/mcp')
@@ -154,7 +156,7 @@ describe('initPeer orchestration', () => {
154
156
  // .mcp.json wired to the daemon with the per-peer identity header
155
157
  expect(r.mcpConfigPaths.length).toBe(1)
156
158
  const mcp = JSON.parse(readFileSync(join(cwd, '.mcp.json'), 'utf8'))
157
- expect(mcp.mcpServers.iapeer.headers['X-IAPeer-Identity']).toBe('claude-mypeer')
159
+ expect(mcp.mcpServers.iapeer.headers['X-IAPeer-Identity']).toBe('${PEER_IDENTITY:-claude-mypeer}')
158
160
  expect(mcp.mcpServers.iapeer.url).toBe('http://127.0.0.1:8765/mcp')
159
161
  // doctrine template created
160
162
  expect(r.doctrineCreated).toBe(true)