@mnemom/mnemom 0.17.0-next.3 → 0.17.0-next.4

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.
@@ -23,7 +23,7 @@
23
23
  * birthThroughGateway (wrap.ts), deriveHashProof (agents.ts), claimAgent +
24
24
  * putAlignmentCard/putProtectionCard (lib/api.ts) — rather than reinventing it.
25
25
  */
26
- import { claimAgent, getAgentByName, getMuBalance, getMyPersonalOrg, MnemomApiError, putAlignmentCard, putProtectionCard, } from "../lib/api.js";
26
+ import { claimAgent, getAgentByName, getMuBalance, getMyPersonalOrg, MnemomApiError, mintProtectionCapability, putAlignmentCard, putProtectionCard, } from "../lib/api.js";
27
27
  import { getAuthInfo, isLoggedIn, loginWithBrowser, loginWithDeviceFlow, resolveAuth, } from "../lib/auth.js";
28
28
  import { getActiveOrg } from "../lib/cli-config.js";
29
29
  import { getWebsiteUrl } from "../lib/config.js";
@@ -63,8 +63,18 @@ export async function ensureGovernedAgent(opts) {
63
63
  const loggedIn = await isLoggedIn();
64
64
  if (loggedIn) {
65
65
  const existing = await getAgentByName(slug).catch(() => null);
66
- if (existing)
66
+ if (existing) {
67
+ // On an EXPLICIT `mnemom code setup`, repair/complete the cards on the
68
+ // already-claimed agent (e.g. a protection card that failed on a prior run
69
+ // before we minted its one-time grant). A bare launch leaves it alone.
70
+ if (opts.setup === true) {
71
+ say(fmt.dim(`mnemom code: '${slug}' is already claimed — refreshing its cards.`));
72
+ await publishDefaultCards(existing.id);
73
+ persistAgentSlug(slug);
74
+ return { slug, provisioned: true };
75
+ }
67
76
  return { slug, provisioned: false };
77
+ }
68
78
  }
69
79
  // 2. Are we allowed to provision here?
70
80
  const canProvision = opts.setup === true || (opts.setup !== false && interactive);
@@ -138,6 +148,18 @@ async function tryPublishCard(name, write) {
138
148
  /** Publish both default observe-only cards; never throws — warns on a card that can't be written. */
139
149
  async function publishDefaultCards(agentId) {
140
150
  const align = await tryPublishCard("alignment", () => putAlignmentCard(agentId, JSON.stringify(buildCodeAlignmentCard(agentId)), "application/json"));
151
+ // Protection is the "locked door": it needs a one-time cards:write:protection
152
+ // grant that the claim does NOT include (alignment rides a standing cap). Mint
153
+ // it with our human login JWT — the "Provision and claim?" confirm is the
154
+ // explicit human approval, and the mint endpoint accepts a human operator (only
155
+ // agent OAuth principals are rejected). The next write consumes the grant. A
156
+ // mint failure falls through to the write's retry + graceful degrade.
157
+ try {
158
+ await mintProtectionCapability(agentId);
159
+ }
160
+ catch {
161
+ // best effort — the protection write below surfaces the real, actionable error
162
+ }
141
163
  const prot = await tryPublishCard("protection", () => putProtectionCard(agentId, JSON.stringify(buildCodeProtectionCard(agentId)), "application/json"));
142
164
  if (align.ok && prot.ok) {
143
165
  say(fmt.success("mnemom code: observe posture published (alignment + protection observe; goal contracts nudge)."));
@@ -148,7 +170,9 @@ async function publishDefaultCards(agentId) {
148
170
  for (const c of [align, prot]) {
149
171
  if (c.ok)
150
172
  continue;
151
- const publishCmd = c.name === "alignment" ? "mnemom card publish" : "mnemom protection publish";
173
+ // Alignment rides a standing cap, so `mnemom card publish` finishes it; the
174
+ // protection grant is one-time, so re-running setup (which re-mints) is the fix.
175
+ const publishCmd = c.name === "alignment" ? "mnemom card publish" : "mnemom code setup";
152
176
  say(fmt.warn(`mnemom code: couldn't publish the ${c.name} card — ${c.error}`));
153
177
  say(fmt.dim(` The agent is claimed and running; finish it later with \`${publishCmd}\`.`));
154
178
  }
package/dist/lib/api.d.ts CHANGED
@@ -394,6 +394,16 @@ export interface MuBalance {
394
394
  enforcementPausedReason?: string | null;
395
395
  }
396
396
  export declare function getMuBalance(orgId?: string): Promise<MuBalance>;
397
+ /**
398
+ * Mint the one-time `cards:write:protection` capability for an agent — the
399
+ * "locked door" that a plain claim does NOT grant (alignment is a standing cap;
400
+ * protection is one-time, 15-min TTL, single-use). `POST
401
+ * /v1/agents/:id/protection-capability` (MNE-876) requires a HUMAN operator
402
+ * (rejects agent OAuth principals) with org co-manage of the agent, so the CLI's
403
+ * own login JWT can mint it — no browser grant needed. Consumed by the very next
404
+ * protection-card write.
405
+ */
406
+ export declare function mintProtectionCapability(agentId: string): Promise<void>;
397
407
  export interface TeamListItem {
398
408
  team_id: string;
399
409
  name: string;
package/dist/lib/api.js CHANGED
@@ -379,6 +379,18 @@ export async function getMuBalance(orgId) {
379
379
  const q = orgId ? `?org_id=${encodeURIComponent(orgId)}` : "";
380
380
  return gFetch(`/v1/billing/mu${q}`, {}, { fallback: "Could not read MU balance" });
381
381
  }
382
+ /**
383
+ * Mint the one-time `cards:write:protection` capability for an agent — the
384
+ * "locked door" that a plain claim does NOT grant (alignment is a standing cap;
385
+ * protection is one-time, 15-min TTL, single-use). `POST
386
+ * /v1/agents/:id/protection-capability` (MNE-876) requires a HUMAN operator
387
+ * (rejects agent OAuth principals) with org co-manage of the agent, so the CLI's
388
+ * own login JWT can mint it — no browser grant needed. Consumed by the very next
389
+ * protection-card write.
390
+ */
391
+ export async function mintProtectionCapability(agentId) {
392
+ await gFetch(`/v1/agents/${encodeURIComponent(agentId)}/protection-capability`, { method: "POST" }, { fallback: "Could not mint the protection capability" });
393
+ }
382
394
  /**
383
395
  * GET /v1/orgs/:org_id/teams for every org the user is a member of,
384
396
  * concatenated. The CLI consumer that just wants "every team I can see"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemom/mnemom",
3
- "version": "0.17.0-next.3",
3
+ "version": "0.17.0-next.4",
4
4
  "description": "Transparent AI agent tracing",
5
5
  "type": "module",
6
6
  "bin": {