import assert from "node:assert/strict"; import crypto from "node:crypto"; import fs from "node:fs"; function canonical(value) { if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`; if (value && typeof value === "object") { return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`; } return JSON.stringify(value); } function digest(value) { return crypto.createHash("sha256").update(canonical(value)).digest("hex"); } function device(name) { const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519"); const publicPem = publicKey.export({ type: "spki", format: "pem" }); return { name, did: `did:key:${digest(publicPem).slice(0, 32)}`, publicKey, privateKey }; } function createEvent(signer, body) { const id = digest(body); const signature = crypto.sign(null, Buffer.from(canonical(body)), signer.privateKey).toString("base64"); return { id, body, signature }; } function verifyEvent(event, keys) { if (digest(event.body) !== event.id) return false; const key = keys.get(event.body.writer); return Boolean(key && crypto.verify(null, Buffer.from(canonical(event.body)), key, Buffer.from(event.signature, "base64"))); } function eventOrder(a, b) { return a.body.clock - b.body.clock || a.id.localeCompare(b.id); } function reduce(events, keys, ownerDid) { const unique = [...new Map(events.map((event) => [event.id, event])).values()].sort(eventOrder); const rejected = []; const grants = new Map(); const revocations = new Map(); for (const event of unique) { if (!verifyEvent(event, keys)) { rejected.push({ id: event.id, reason: "bad-signature-or-id" }); continue; } const { kind, writer, payload, clock } = event.body; if (kind === "grant.issue") { if (writer !== ownerDid) rejected.push({ id: event.id, reason: "non-owner-grant" }); else grants.set(payload.grant_id, payload); } if (kind === "grant.revoke") { if (writer !== ownerDid) rejected.push({ id: event.id, reason: "non-owner-revocation" }); else revocations.set(payload.grant_id, clock); } } const registers = new Map(); for (const event of unique) { if (!verifyEvent(event, keys) || event.body.kind !== "state.put") continue; const { writer, clock, payload, grant_id: grantId } = event.body; const grant = grants.get(grantId); const revokedAt = revocations.get(grantId); let reason = null; if (!grant) reason = "missing-grant"; else if (grant.grantee !== writer) reason = "wrong-grantee"; else if (!grant.actions.includes("state.put")) reason = "action-not-allowed"; else if (clock > grant.expires_at) reason = "expired-grant"; else if (revokedAt !== undefined && clock >= revokedAt) reason = "revoked-grant"; if (reason) { rejected.push({ id: event.id, reason }); continue; } const current = registers.get(payload.path); if (!current || eventOrder(current.event, event) < 0) registers.set(payload.path, { value: payload.value, event }); } const state = Object.fromEntries([...registers.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([path, item]) => [path, item.value])); return { state, state_hash: digest(state), accepted_events: unique.length - rejected.length, rejected }; } function exportHarnessA(internal, signer, ownerDid, grantId, startClock) { const events = []; let clock = startClock; const put = (path, value) => events.push(createEvent(signer, { version: "probe-0.1", owner: ownerDid, writer: signer.did, clock: clock++, kind: "state.put", grant_id: grantId, payload: { path, value } })); for (const [key, value] of Object.entries(internal.user.preferences)) put(`profile.preferences.${key}`, value); for (const memory of internal.memories) put(`memory.${memory.id}`, { text: memory.text, provenance: memory.source }); put("task.current", internal.task); return { events, loss: ["tool_rules: target-independent execution semantics undefined"], omitted: ["private_material: never serialized"] }; } function importHarnessB(state) { const profile = { preferences: {} }; const recollections = {}; let work = null; for (const [path, value] of Object.entries(state)) { if (path.startsWith("profile.preferences.")) profile.preferences[path.split(".").at(-1)] = value; else if (path.startsWith("memory.")) recollections[path.split(".").at(-1)] = value; else if (path === "task.current") work = value; } return { profile, recollections, work, vault: "local-only" }; } function auditAgentFile(path) { if (!path) return null; const file = JSON.parse(fs.readFileSync(path, "utf8")); const agents = file.agents ?? []; return { format: "Letta Agent File", agents: agents.length, blocks: (file.blocks ?? []).length, tools: (file.tools ?? []).length, messages: agents.reduce((sum, agent) => sum + (agent.messages ?? []).length, 0), contains_secret_values: agents.some((agent) => Object.values(agent.secrets ?? {}).some((value) => value !== null)), known_portability_gaps: ["archival passages not represented", "framework-specific blocks/tool rules require adapters", "schema migration is roadmap work"] }; } const owner = device("owner"); const harnessA = device("harness-a"); const harnessB = device("harness-b"); const keys = new Map([[owner.did, owner.publicKey], [harnessA.did, harnessA.publicKey], [harnessB.did, harnessB.publicKey]]); const grantA = createEvent(owner, { version: "probe-0.1", owner: owner.did, writer: owner.did, clock: 1, kind: "grant.issue", payload: { grant_id: "grant-a", grantee: harnessA.did, actions: ["state.put"], expires_at: 100 } }); const grantB = createEvent(owner, { version: "probe-0.1", owner: owner.did, writer: owner.did, clock: 2, kind: "grant.issue", payload: { grant_id: "grant-b", grantee: harnessB.did, actions: ["state.put"], expires_at: 100 } }); const internalA = { user: { preferences: { language: "zh-CN", answer_style: "direct" } }, memories: [{ id: "m1", text: "User works in Beijing", source: "user-stated" }], task: { id: "research-1", status: "active", title: "portable state research" }, tool_rules: [{ tool: "shell", allow: "workspace-only" }], private_material: { demo_credential: "redacted-local-only" } }; const exportedA = exportHarnessA(internalA, harnessA, owner.did, "grant-a", 10); const base = reduce([grantA, grantB, ...exportedA.events], keys, owner.did); const importedB = importHarnessB(base.state); const concurrentA = createEvent(harnessA, { version: "probe-0.1", owner: owner.did, writer: harnessA.did, clock: 20, kind: "state.put", grant_id: "grant-a", payload: { path: "profile.preferences.theme", value: "dark" } }); const concurrentB = createEvent(harnessB, { version: "probe-0.1", owner: owner.did, writer: harnessB.did, clock: 20, kind: "state.put", grant_id: "grant-b", payload: { path: "profile.preferences.theme", value: "light" } }); const mergedAB = reduce([grantA, grantB, ...exportedA.events, concurrentA, concurrentB], keys, owner.did); const mergedBA = reduce([concurrentB, ...exportedA.events, grantB, concurrentA, grantA], keys, owner.did); const tampered = structuredClone(exportedA.events[0]); tampered.body.payload.value = "tampered"; const tamperResult = reduce([grantA, tampered], keys, owner.did); const revokeB = createEvent(owner, { version: "probe-0.1", owner: owner.did, writer: owner.did, clock: 30, kind: "grant.revoke", payload: { grant_id: "grant-b" } }); const postRevoke = createEvent(harnessB, { version: "probe-0.1", owner: owner.did, writer: harnessB.did, clock: 31, kind: "state.put", grant_id: "grant-b", payload: { path: "profile.preferences.language", value: "en-US" } }); const revokeResult = reduce([grantA, grantB, ...exportedA.events, revokeB, postRevoke], keys, owner.did); const tests = []; const test = (name, fn) => { fn(); tests.push({ name, status: "pass" }); }; test("cross-harness preference import", () => assert.equal(importedB.profile.preferences.language, "zh-CN")); test("cross-harness memory import", () => assert.equal(importedB.recollections.m1.text, "User works in Beijing")); test("cross-harness task import", () => assert.equal(importedB.work.status, "active")); test("merge converges independent of delivery order", () => assert.equal(mergedAB.state_hash, mergedBA.state_hash)); test("concurrent conflict resolves deterministically", () => assert.equal(mergedAB.state["profile.preferences.theme"], mergedBA.state["profile.preferences.theme"])); test("tampering is rejected", () => assert.equal(tamperResult.rejected[0].reason, "bad-signature-or-id")); test("revoked grant blocks later write", () => assert.ok(revokeResult.rejected.some((item) => item.reason === "revoked-grant"))); test("pre-revocation state remains valid", () => assert.equal(revokeResult.state["profile.preferences.language"], "zh-CN")); test("secrets are omitted", () => assert.ok(!canonical(exportedA).includes("redacted-local-only"))); test("semantic loss is explicit", () => assert.ok(exportedA.loss[0].includes("tool_rules"))); const result = { experiment: "portable-state-probe", runtime: process.version, tests, summary: { passed: tests.length, failed: 0, canonical_state_fields: Object.keys(base.state).length, converged_state_hash: mergedAB.state_hash, tamper_rejections: tamperResult.rejected.length, revocation_rejections: revokeResult.rejected.filter((item) => item.reason === "revoked-grant").length, explicit_loss_items: exportedA.loss.length, omitted_secret_classes: exportedA.omitted.length }, interpretation: { demonstrated: ["signed event portability", "deterministic merge", "capability revocation", "secret omission", "loss reporting"], not_demonstrated: ["behavioral equivalence across real model runtimes", "large-scale sync performance", "key recovery", "multi-user policy composition"] }, agent_file_audit: auditAgentFile(process.argv[2]) }; console.log(JSON.stringify(result, null, 2));