feat(broker+cli): apikey create/list/revoke verbs (v0.2.0 #71)
Issuance flow over WS for now (REST endpoints come next slice). Plaintext secret returned ONCE on create — never recoverable. - broker: 3 WS handlers (apikey_create/list/revoke), wire types in union, audit log on issuance + revoke - ws-client: apiKeyCreate/List/Revoke with resolver maps, response dispatch - CLI: claudemesh apikey create <label> [--cap a,b] [--topic c,d] [--expires ISO]; list shows status, scope, last-used; revoke by id - policy: apikey create + revoke prompt by default (issuing or disabling a credential is meaningful) Default capability set is "send,read" — least privilege for unscoped keys (admin must explicitly opt-in). Spec: .artifacts/specs/2026-05-02-v0.2.0-scope.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,11 @@ Profile / presence (resource form)
|
||||
claudemesh group join @<name> join a group (--role X)
|
||||
claudemesh group leave @<name> leave a group
|
||||
|
||||
API keys (REST + external WS auth, v0.2.0)
|
||||
claudemesh apikey create <label> issue [--cap send,read] [--topic deploys]
|
||||
claudemesh apikey list show keys (status, last-used, scope)
|
||||
claudemesh apikey revoke <id> revoke a key
|
||||
|
||||
Topic (conversation scope, v0.2.0)
|
||||
claudemesh topic create <name> create a topic [--description --visibility]
|
||||
claudemesh topic list list topics in the mesh
|
||||
@@ -509,6 +514,24 @@ async function main(): Promise<void> {
|
||||
break;
|
||||
}
|
||||
|
||||
// apikey — REST + external WS bearer tokens (v0.2.0)
|
||||
case "apikey": case "api-key": {
|
||||
const sub = positionals[0];
|
||||
const f = {
|
||||
mesh: flags.mesh as string,
|
||||
json: !!flags.json,
|
||||
cap: flags.cap as string,
|
||||
topic: flags.topic as string,
|
||||
expires: flags.expires as string,
|
||||
};
|
||||
const arg = positionals[1] ?? "";
|
||||
if (sub === "create") { const { runApiKeyCreate } = await import("~/commands/apikey.js"); process.exit(await runApiKeyCreate(arg, f)); }
|
||||
else if (sub === "list") { const { runApiKeyList } = await import("~/commands/apikey.js"); process.exit(await runApiKeyList(f)); }
|
||||
else if (sub === "revoke") { const { runApiKeyRevoke } = await import("~/commands/apikey.js"); process.exit(await runApiKeyRevoke(arg, f)); }
|
||||
else { console.error("Usage: claudemesh apikey <create|list|revoke>"); process.exit(EXIT.INVALID_ARGS); }
|
||||
break;
|
||||
}
|
||||
|
||||
// topic — conversational primitive within a mesh (v0.2.0)
|
||||
case "topic": {
|
||||
const sub = positionals[0];
|
||||
|
||||
Reference in New Issue
Block a user