@amkentech/agent-channel 0.8.0 → 0.8.1
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 +1 -1
- package/scripts/artifact.mjs +32 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amkentech/agent-channel",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "One identity for every AI coding session you run: Claude Code, Codex, Desktop, Cursor, Gemini, Windsurf share one inbox, hand tasks to each other, and message other people's agents. Encrypted files and read-only share links included. The server is a separate, private service.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/scripts/artifact.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { readFileSync, statSync, writeFileSync, mkdirSync, existsSync, readdirSy
|
|
|
15
15
|
import { basename, join, resolve, dirname } from "node:path";
|
|
16
16
|
import { createHash } from "node:crypto";
|
|
17
17
|
import { homedir } from "node:os";
|
|
18
|
-
import { encryptFor, ensureKey, sha256hex, generateKeypair, findLocalKey, saveLocalKey } from "../lib/crypto.mjs";
|
|
18
|
+
import { encryptFor, ensureKey, sha256hex, generateKeypair, findLocalKey, saveLocalKey, decryptWith, loadLocalKeys } from "../lib/crypto.mjs";
|
|
19
19
|
import { fetchArtifact } from "../lib/artifacts.mjs";
|
|
20
20
|
|
|
21
21
|
const args = process.argv.slice(2);
|
|
@@ -109,6 +109,37 @@ try {
|
|
|
109
109
|
} else {
|
|
110
110
|
await fetchArtifact({ base: BASE, token, handle: me.handle, id: args[1] });
|
|
111
111
|
}
|
|
112
|
+
} else if (cmd === "org-keygen") {
|
|
113
|
+
// Enterprise custody: the ORG key is generated here, on the claimant's machine, and only the PUBLIC half is ever
|
|
114
|
+
// registered (set_org_escrow). key_id is deterministic from the domain so envelopes and this key store agree.
|
|
115
|
+
const me = await myHandle();
|
|
116
|
+
const domain = (flag("--domain") || "").toLowerCase();
|
|
117
|
+
if (!domain) { console.error("usage: artifact.mjs org-keygen --domain <your-verified-org-domain>"); process.exit(1); }
|
|
118
|
+
const label = "org-escrow-" + domain;
|
|
119
|
+
if (findLocalKey(me.handle, label) && !has("--force")) { console.error("an org key for " + domain + " already exists locally (" + label + "). --force replaces it; the old one stays on disk renamed only if you rename it yourself."); process.exit(1); }
|
|
120
|
+
const k = generateKeypair();
|
|
121
|
+
saveLocalKey(me.handle, label, { key_id: label, ...k });
|
|
122
|
+
console.log("org escrow keypair for " + domain + " generated. Private key stays in ~/.agentchan/" + me.handle + "/keys/ (0600). BACK IT UP: without it, escrowed files are unreadable to the org.");
|
|
123
|
+
console.log("register the public half (your agent runs set_org_escrow):\n public_key: " + k.public_key);
|
|
124
|
+
} else if (cmd === "org-list") {
|
|
125
|
+
const r = await api("/org/artifacts");
|
|
126
|
+
if (!r.artifacts.length) { console.log("no live artifacts among " + r.org + " members"); }
|
|
127
|
+
for (const a of r.artifacts) console.log(a.id + " " + a.from_handle + " -> " + a.to_handle + " " + a.filename + " (" + a.size_bytes + " B) expires " + a.expires_at);
|
|
128
|
+
if (r.artifacts.length) console.log("\nFetch one: node scripts/artifact.mjs org-fetch <id> (the member is notified; the fetch is on the ledger)");
|
|
129
|
+
} else if (cmd === "org-fetch") {
|
|
130
|
+
const me = await myHandle();
|
|
131
|
+
if (!args[1]) { console.error("usage: artifact.mjs org-fetch <artifact_id>"); process.exit(1); }
|
|
132
|
+
const a = await api("/org/artifacts/" + args[1]);
|
|
133
|
+
const plain = decryptWith(loadLocalKeys(me.handle), a.envelope, a.ciphertext);
|
|
134
|
+
const { inspectArtifact, safeName } = await import("../lib/inspect.mjs");
|
|
135
|
+
const report = inspectArtifact({ filename: a.filename, bytes: plain, declaredSha256: a.sha256, actualSha256: sha256hex(plain) });
|
|
136
|
+
const dir = join(homedir(), ".agentchan", me.handle, "org-audit", String(args[1]).slice(0, 8));
|
|
137
|
+
mkdirSync(dir, { recursive: true });
|
|
138
|
+
const out = join(dir, safeName(a.filename));
|
|
139
|
+
writeFileSync(out, plain);
|
|
140
|
+
writeFileSync(join(dir, "report.json"), JSON.stringify({ ...report, from: a.from, to: a.to, fetched_by: "@" + me.handle, org_escrow: true }, null, 2));
|
|
141
|
+
console.log("decrypted " + a.filename + " (" + a.from + " -> " + a.to + ") to " + out + " [" + report.verdict + "]");
|
|
142
|
+
console.log("the member was notified of this fetch, and it is on the audit ledger.");
|
|
112
143
|
} else if (cmd === "keygen") {
|
|
113
144
|
const me = await myHandle();
|
|
114
145
|
const label = flag("--label") || (me.agent + "-" + me.runtime + "-" + (process.env.COMPUTERNAME || process.env.HOSTNAME || "host")).toLowerCase();
|