@botiverse/hands-cli 0.5.15 → 0.5.16

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.
@@ -18,8 +18,7 @@
18
18
  * - Reuses the existing CLI identity/token; no scope escalation.
19
19
  */
20
20
  import { readFile, writeFile } from "node:fs/promises";
21
- import { getApiBase } from "../lib/api.js";
22
- import { resolveAuthToken } from "../lib/config.js";
21
+ import { getApiBase, agentAwareFetch } from "../lib/api.js";
23
22
  const METHODS = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"]);
24
23
  /**
25
24
  * Resolve `pathArg` against the Hands API base and enforce that it is a
@@ -86,19 +85,22 @@ export function registerApiCommand(program) {
86
85
  ? await readFile(opts.data.slice(1), "utf8")
87
86
  : opts.data;
88
87
  }
89
- const headers = { accept: "application/json" };
90
- const token = resolveAuthToken();
91
- if (token)
92
- headers.authorization = `Bearer ${token}`;
93
- if (body !== undefined)
94
- headers["content-type"] = "application/json";
95
- const res = await fetch(target.toString(), {
96
- method,
97
- headers,
98
- ...(body !== undefined ? { body } : {}),
99
- // Never auto-follow a 3xx: a redirect off the API origin would carry
100
- // the bearer token to the redirect target.
101
- redirect: "manual",
88
+ // Agent-aware: proactive refresh + one guarded 401 retry in agent mode, same as
89
+ // every other CLI HTTP path. The request is rebuilt per attempt with the bearer.
90
+ const res = await agentAwareFetch((bearer) => {
91
+ const headers = { accept: "application/json" };
92
+ if (bearer)
93
+ headers.authorization = `Bearer ${bearer}`;
94
+ if (body !== undefined)
95
+ headers["content-type"] = "application/json";
96
+ return fetch(target.toString(), {
97
+ method,
98
+ headers,
99
+ ...(body !== undefined ? { body } : {}),
100
+ // Never auto-follow a 3xx: a redirect off the API origin would carry
101
+ // the bearer token to the redirect target.
102
+ redirect: "manual",
103
+ });
102
104
  });
103
105
  const requestId = res.headers.get("x-request-id") ?? res.headers.get("cf-ray");
104
106
  const statusLine = `${res.status} ${res.statusText}${requestId ? ` request-id=${requestId}` : ""}`;
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3E;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,OAAe;IACtE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,iBAAiB,OAAO,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb,aAAa,OAAO,mBAAmB,IAAI,CAAC,MAAM,eAAe;YAC/D,gDAAgD,CACnD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,aAAa,MAAM,CAAC,QAAQ,gCAAgC,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,OAAO;SACJ,OAAO,CAAC,qBAAqB,CAAC;SAC9B,WAAW,CACV,gEAAgE;QAC9D,wEAAwE,CAC3E;SACA,MAAM,CAAC,iBAAiB,EAAE,yCAAyC,CAAC;SACpE,MAAM,CAAC,qBAAqB,EAAE,4DAA4D,CAAC;SAC3F,MAAM,CAAC,iBAAiB,EAAE,8DAA8D,CAAC;SACzF,MAAM,CAAC,QAAQ,EAAE,sDAAsD,EAAE,KAAK,CAAC;SAC/E,MAAM,CACL,KAAK,EACH,SAAiB,EACjB,OAAe,EACf,IAA0E,EAC1E,OAAgB,EAChB,EAAE;QACF,0EAA0E;QAC1E,0DAA0D;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,eAAe,EAAsB,CAAC,IAAI,CAAC;QACjF,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,uBAAuB,SAAS,kBAAkB,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,MAAW,CAAC;QAChB,IAAI,CAAC;YACH,wEAAwE;YACxE,sEAAsE;YACtE,MAAM,GAAG,uBAAuB,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC;gBAAE,IAAI,CAAC,oBAAoB,EAAE,wBAAwB,CAAC,CAAC;YAClE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,IAAwB,CAAC;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAC9B,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;gBAC5C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,OAAO,GAA2B,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QACvE,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;QACjC,IAAI,KAAK;YAAE,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;QACrD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;QAErE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE;YACzC,MAAM;YACN,OAAO;YACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,qEAAqE;YACrE,2CAA2C;YAC3C,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/E,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAChD,SAAS,CAAC,CAAC,CAAC,gBAAgB,SAAS,EAAE,CAAC,CAAC,CAAC,EAC5C,EAAE,CAAC;QAEH,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CACX,GAAG,UAAU,iBAAiB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,QAAQ,gBAAgB;gBACnF,yDAAyD,CAC5D,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;YACnD,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpC,OAAO,CAAC,KAAK,CAAC,GAAG,UAAU,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;YACzE,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CACF,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"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"}
@@ -15,8 +15,11 @@
15
15
  */
16
16
  import { createInterface } from "node:readline/promises";
17
17
  import { stdin, stdout } from "node:process";
18
- import { apiRequest, getApiBase, QuiverApiError } from "../lib/api.js";
19
- import { clearConfig, saveConfig, getConfig } from "../lib/config.js";
18
+ import { rmSync } from "node:fs";
19
+ import { apiRequest, getApiBase, setApiBase, QuiverApiError } from "../lib/api.js";
20
+ import { clearConfig, saveConfig, getConfig, configPath } from "../lib/config.js";
21
+ import { admitAgent, agentAuthPath, HANDS_SERVICE } from "../lib/agent_env.js";
22
+ import { runAgentLogin } from "../lib/agent_auth.js";
20
23
  async function promptSecret(message) {
21
24
  // Use a raw-mode readline so we can mask input with '*'.
22
25
  const rl = createInterface({ input: stdin, output: stdout, terminal: true });
@@ -61,6 +64,38 @@ export function registerLoginCommands(program) {
61
64
  .option("--print-url", "Just print the login URL; don't prompt for a token.", false)
62
65
  .action(async (opts) => {
63
66
  const apiBase = opts.api ?? getApiBase();
67
+ const admission = admitAgent();
68
+ // Managed-agent path (RFC 057): no browser, no paste. Runs agent-login →
69
+ // exchange → store under $SLOCK_HOME. Isolated from the human config.
70
+ if (admission.kind === "agent") {
71
+ if (opts.token) {
72
+ // Never let --token write the human config from inside an agent.
73
+ console.error("✘ In a managed agent environment, run `hands login` without --token (agent-login is used instead).");
74
+ process.exit(1);
75
+ }
76
+ if (opts.printUrl) {
77
+ console.log("(agent environment) `hands login` runs the non-interactive agent-login flow — no URL to open.");
78
+ return;
79
+ }
80
+ setApiBase(apiBase); // exchange must target this API base
81
+ try {
82
+ const session = await runAgentLogin(admission.env);
83
+ console.log(`✔ Agent login complete (service ${HANDS_SERVICE}).`);
84
+ console.log(` Stored under $SLOCK_HOME/agents/$SLOCK_AGENT_ID/integrations/${HANDS_SERVICE}/auth.json`);
85
+ console.log(` access token expires ${session.access_expires_at}; refresh rotates automatically.`);
86
+ console.log(" Subsequent `hands` commands use the stored Hands token directly.");
87
+ }
88
+ catch (e) {
89
+ console.error(`✘ Agent login failed: ${e instanceof Error ? e.message : String(e)}`);
90
+ process.exit(1);
91
+ }
92
+ return;
93
+ }
94
+ if (admission.kind === "fail_closed") {
95
+ // Partial/invalid agent markers must never silently use human credentials.
96
+ console.error(`✘ Agent environment is incomplete or invalid (${admission.reason}); refusing to fall back to human login. Fix the agent environment and retry.`);
97
+ process.exit(1);
98
+ }
64
99
  const loginUrl = `${apiBase}/api/auth/login?return_to=${encodeURIComponent("/cli/callback")}`;
65
100
  if (opts.printUrl) {
66
101
  console.log(loginUrl);
@@ -85,7 +120,7 @@ export function registerLoginCommands(program) {
85
120
  // Persist the token + apiBase to config file.
86
121
  clearConfig();
87
122
  saveConfig({ apiBase, authToken: token });
88
- console.log(`✔ Saved to ${configDisplayPath()}`);
123
+ console.log(`✔ Saved to ${configPath()}`);
89
124
  console.log(` API base: ${apiBase}`);
90
125
  // Verify the token works by calling /api/auth/me.
91
126
  try {
@@ -110,22 +145,34 @@ export function registerLoginCommands(program) {
110
145
  });
111
146
  program
112
147
  .command("logout")
113
- .description("Clear the saved Hands JWT.")
148
+ .description("Clear the saved Hands token (agent store in an agent, else human config).")
114
149
  .action(() => {
150
+ const admission = admitAgent();
151
+ if (admission.kind === "agent") {
152
+ // Clear the per-agent store only; never touch the human config.
153
+ const path = agentAuthPath(admission.env);
154
+ try {
155
+ rmSync(path, { force: true });
156
+ console.log(`✔ Agent Hands token cleared (${path}).`);
157
+ }
158
+ catch (e) {
159
+ console.error(`✘ Failed to clear agent token: ${e instanceof Error ? e.message : String(e)}`);
160
+ process.exit(1);
161
+ }
162
+ return;
163
+ }
164
+ if (admission.kind === "fail_closed") {
165
+ console.error(`✘ Agent environment is incomplete or invalid (${admission.reason}).`);
166
+ process.exit(1);
167
+ }
115
168
  const cfg = getConfig();
116
169
  if (!cfg.authToken && !cfg.sessionCookie) {
117
- console.log("Not logged in (no saved Hands JWT).");
170
+ console.log("Not logged in (no saved Hands token).");
118
171
  return;
119
172
  }
120
173
  clearConfig();
121
- console.log(`✔ Logged out (token cleared from ${configDisplayPath()}).`);
174
+ console.log(`✔ Logged out (token cleared from ${configPath()}).`);
122
175
  });
123
176
  }
124
- function configDisplayPath() {
125
- // Mirror getConfig's path resolution for display only.
126
- const xdg = process.env.XDG_CONFIG_HOME;
127
- const dir = xdg && xdg.length > 0 ? xdg : `${process.env.HOME ?? "~"}/.config`;
128
- return `${dir}/quiver/auth.json`;
129
- }
130
177
  // Keep the command module side-effect free when imported by tests.
131
178
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,8 @@ const NO_AUTH_HELP = "Not authenticated. Choose one:\n" +
8
8
  " • Agents / CI: set HANDS_BEARER_TOKEN to a deploy token\n" +
9
9
  " (console → App → Settings → Deploy Tokens; publisher role to release).\n" +
10
10
  " • Humans: run `hands login` and paste the browser callback JWT.\n" +
11
- " • Raft agents: run `raft integration login --service <hands-service>` and use\n" +
12
- " the integration session through `raft integration invoke`.";
11
+ " • Raft agents: run `hands login` it auto-detects the managed agent and completes\n" +
12
+ " the agent-login handshake via your Raft integration session (no URL to open).";
13
13
  export function registerWhoamiCommand(program) {
14
14
  program
15
15
  .command("whoami")
@@ -1 +1 @@
1
- {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,YAAY,GAChB,kCAAkC;IAClC,6DAA6D;IAC7D,gFAAgF;IAChF,qEAAqE;IACrE,mFAAmF;IACnF,kEAAkE,CAAC;AAmBrE,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,oDAAoD,CAAC;SACjE,MAAM,CAAC,QAAQ,EAAE,+BAA+B,EAAE,KAAK,CAAC;SACxD,MAAM,CAAC,KAAK,EAAE,IAAwB,EAAE,EAAE;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,UAAU,CAAa,cAAc,CAAC,CAAC;YACxD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzC,OAAO;YACT,CAAC;YACD,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,MAAM,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,cAAc,UAAU,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,cAAc,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACpD,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,MAAM,YAAY,GAChB,kCAAkC;IAClC,6DAA6D;IAC7D,gFAAgF;IAChF,qEAAqE;IACrE,wFAAwF;IACxF,qFAAqF,CAAC;AAmBxF,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,oDAAoD,CAAC;SACjE,MAAM,CAAC,QAAQ,EAAE,+BAA+B,EAAE,KAAK,CAAC;SACxD,MAAM,CAAC,KAAK,EAAE,IAAwB,EAAE,EAAE;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,UAAU,CAAa,cAAc,CAAC,CAAC;YACxD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzC,OAAO;YACT,CAAC;YACD,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,MAAM,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,cAAc,UAAU,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,cAAc,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACpD,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { type AgentEnv } from "./agent_env.js";
2
+ /** PKCE S256: 64-byte verifier → 86 unreserved base64url chars (within RFC 7636's
3
+ * 43–128), challenge = unpadded base64url SHA-256. */
4
+ export declare function generatePkce(): {
5
+ verifier: string;
6
+ challenge: string;
7
+ };
8
+ /**
9
+ * Strictly validate a `raft integration invoke --action agent-login --json` result.
10
+ * Real envelope (verified against the live daemon):
11
+ * { ok:true, data:{ service, action, status, result:{schema,service,grant,expires_at} } }
12
+ * The Hands-owned `result` is closed-key validated; the Raft envelope (outer/data) is
13
+ * validated by exact required values. NO part of stdout is ever echoed in an error.
14
+ */
15
+ export declare function parseAgentLoginInvoke(stdout: string, service: string, now: number): {
16
+ grant: string;
17
+ expires_at: string;
18
+ };
19
+ export interface AgentSession {
20
+ schema: "raft-cli-agent-session.v1";
21
+ token_type: "Bearer";
22
+ access_token: string;
23
+ access_expires_at: string;
24
+ refresh_token: string;
25
+ refresh_expires_at: string | null;
26
+ }
27
+ /**
28
+ * Strictly validate the exchange/refresh success body (closed keys + RFC3339).
29
+ * `now` is injected so validation is deterministic: a freshly issued session MUST
30
+ * have a strictly-future access expiry (and refresh expiry, when present) — otherwise
31
+ * we would persist an already-dead session that the very next request must refresh.
32
+ */
33
+ export declare function parseAgentSession(body: any, now: number): AgentSession;
34
+ export interface StoredAgentAuth extends AgentSession {
35
+ service: string;
36
+ api_base: string;
37
+ updated_at: string;
38
+ }
39
+ /**
40
+ * Atomic, hardened store write: O_EXCL unique temp in the same dir, 0600, write +
41
+ * fsync + close, atomic rename. Each dir component under $SLOCK_HOME is ensured AND
42
+ * verified 0700 (repairing a pre-existing wide dir). $SLOCK_HOME itself is not chmod'd.
43
+ * On any failure the temp is removed and the previous file is left intact.
44
+ */
45
+ export declare function writeAgentSession(a: AgentEnv, service: string, session: AgentSession, apiBase: string, now?: () => string): string;
46
+ export declare const MAX_TOKEN_RESPONSE_BYTES: number;
47
+ /**
48
+ * Read a response body with a hard byte cap. If an AbortController is supplied it is
49
+ * aborted when the cap is exceeded (so a still-open connection is torn down, and — in
50
+ * `rotate` — the same controller's deadline keeps covering this read). Falls back to
51
+ * `.text()` for response doubles that expose no stream (still cap-checked).
52
+ */
53
+ export declare function readBoundedText(res: Response, controller?: AbortController): Promise<string>;
54
+ export interface AgentLoginOptions {
55
+ service?: string;
56
+ now?: number;
57
+ /** Injectable invoke runner for tests; defaults to spawning the pinned wrapper. */
58
+ invoke?: (args: string[]) => {
59
+ status: number | null;
60
+ stdout: string;
61
+ stderr: string;
62
+ };
63
+ /** Injectable fetch for the exchange; defaults to global fetch. */
64
+ fetchImpl?: typeof fetch;
65
+ }
66
+ /**
67
+ * Full agent-login flow: invoke the pinned wrapper → strict-validate grant → exchange
68
+ * → strict-validate session → atomic store. Returns the stored session on success.
69
+ */
70
+ export declare function runAgentLogin(a: AgentEnv, opts?: AgentLoginOptions): Promise<AgentSession>;
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Agent CLI login flow (RFC 057, CP3): the non-interactive `hands login` used inside
3
+ * a managed Raft agent. No browser, no paste.
4
+ *
5
+ * 1. Generate a PKCE code_verifier locally; send only its S256 challenge to Raft.
6
+ * 2. Run the EXACT wrapper `$SLOCK_CLI_TRANSPORT_DIR/raft integration invoke
7
+ * --action agent-login --json` (never PATH `raft`); require exit 0; STRICTLY
8
+ * validate the result (outer success + exact service/action/status + closed grant
9
+ * result schema + RFC3339/future expiry within a bounded client sanity window). The
10
+ * server issues a 300s TTL (RFC 057) and enforces the real expiry; the client accepts
11
+ * up to 300s + clock-skew headroom so a boundary grant is not rejected under skew.
12
+ * Errors carry only stable reasons
13
+ * — never the raw stdout/stderr/body (which could contain grant/action payload).
14
+ * 3. Exchange { grant, code_verifier } at the Hands PUBLIC endpoint for a
15
+ * raft-cli-agent-session.v1; strictly validate it (closed keys + RFC3339 expiries).
16
+ * 4. Atomically persist under $SLOCK_HOME (O_EXCL temp + fsync + rename; 0600 file /
17
+ * verified-0700 dirs), recording the api base so the resolver never needs config.
18
+ *
19
+ * The verifier never reaches Raft, logs, or the store. Only the Hands token is stored.
20
+ */
21
+ import { spawnSync } from "node:child_process";
22
+ import { openSync, writeSync, fsyncSync, closeSync, renameSync, rmSync, mkdirSync, statSync, chmodSync, } from "node:fs";
23
+ import { join } from "node:path";
24
+ import { randomBytes, createHash } from "node:crypto";
25
+ import { getApiBase } from "./api.js";
26
+ import { agentAuthPath, HANDS_SERVICE } from "./agent_env.js";
27
+ function base64url(buf) {
28
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
29
+ }
30
+ /** PKCE S256: 64-byte verifier → 86 unreserved base64url chars (within RFC 7636's
31
+ * 43–128), challenge = unpadded base64url SHA-256. */
32
+ export function generatePkce() {
33
+ const verifier = base64url(randomBytes(64));
34
+ const challenge = base64url(createHash("sha256").update(verifier).digest());
35
+ return { verifier, challenge };
36
+ }
37
+ function hasExactKeys(o, keys) {
38
+ const k = Object.keys(o);
39
+ return k.length === keys.length && keys.every((key) => Object.prototype.hasOwnProperty.call(o, key));
40
+ }
41
+ /** Parse an RFC3339 date-time to epoch ms, or null. Rejects bare dates / bad offsets. */
42
+ function parseRfc3339(s) {
43
+ if (typeof s !== "string")
44
+ return null;
45
+ if (!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(Z|[+-]\d\d:\d\d)$/.test(s))
46
+ return null;
47
+ const t = Date.parse(s);
48
+ return Number.isFinite(t) ? t : null;
49
+ }
50
+ // Client-side sanity ceiling on the grant lifetime: the server issues expiry =
51
+ // server_now + 300s (RFC 057). We allow generous clock-skew headroom above that so a
52
+ // legitimate grant is never rejected at the exact boundary; the server enforces the
53
+ // real, shorter expiry, so this bound only rejects an absurdly long-lived grant.
54
+ const AGENT_GRANT_TTL_CEILING_MS = 300_000 + 120_000; // 300s + 120s skew
55
+ /**
56
+ * Strictly validate a `raft integration invoke --action agent-login --json` result.
57
+ * Real envelope (verified against the live daemon):
58
+ * { ok:true, data:{ service, action, status, result:{schema,service,grant,expires_at} } }
59
+ * The Hands-owned `result` is closed-key validated; the Raft envelope (outer/data) is
60
+ * validated by exact required values. NO part of stdout is ever echoed in an error.
61
+ */
62
+ export function parseAgentLoginInvoke(stdout, service, now) {
63
+ let outer;
64
+ try {
65
+ outer = JSON.parse(stdout);
66
+ }
67
+ catch {
68
+ throw new Error("agent-login: `raft integration invoke` did not return JSON");
69
+ }
70
+ if (!outer || typeof outer !== "object")
71
+ throw new Error("agent-login: invoke output is not an object");
72
+ // Check success first: a failed invoke may legitimately carry a different shape
73
+ // (e.g. {ok:false, error}); only the success wrapper is the closed {ok, data}.
74
+ if (outer.ok !== true)
75
+ throw new Error("agent-login: invoke did not succeed");
76
+ // Closed envelope: an unexpected extra field means the wire drifted from the
77
+ // checkpoint contract; fail rather than ignore.
78
+ if (!hasExactKeys(outer, ["ok", "data"]))
79
+ throw new Error("agent-login: invoke envelope has unexpected fields");
80
+ const data = outer.data;
81
+ if (!data || typeof data !== "object")
82
+ throw new Error("agent-login: invoke result is missing data");
83
+ if (!hasExactKeys(data, ["service", "action", "status", "result"])) {
84
+ throw new Error("agent-login: invoke data has unexpected fields");
85
+ }
86
+ if (data.service !== service)
87
+ throw new Error("agent-login: invoke service does not match the requested service");
88
+ if (data.action !== "agent-login")
89
+ throw new Error("agent-login: invoke action is not agent-login");
90
+ if (data.status !== 200)
91
+ throw new Error("agent-login: agent-login action did not return HTTP 200");
92
+ const result = data.result;
93
+ if (!result || typeof result !== "object")
94
+ throw new Error("agent-login: invoke result is missing the grant body");
95
+ if (!hasExactKeys(result, ["schema", "service", "grant", "expires_at"])) {
96
+ throw new Error("agent-login: grant result has unexpected fields");
97
+ }
98
+ if (result.schema !== "raft-cli-agent-login-grant.v1")
99
+ throw new Error("agent-login: unexpected grant result schema");
100
+ if (result.service !== service)
101
+ throw new Error("agent-login: grant result service mismatch");
102
+ if (typeof result.grant !== "string" || result.grant.length === 0)
103
+ throw new Error("agent-login: grant is missing");
104
+ const exp = parseRfc3339(result.expires_at);
105
+ if (exp === null)
106
+ throw new Error("agent-login: grant expires_at is not an RFC3339 timestamp");
107
+ if (exp <= now)
108
+ throw new Error("agent-login: grant is already expired");
109
+ // The server issues expiry = server_now + 300s (RFC 057). The client parses it later and
110
+ // its clock may differ, so a zero-tolerance ceiling flakes at the exact boundary. This is
111
+ // a sanity bound (the server enforces the real expiry), so allow clock-skew headroom.
112
+ if (exp > now + AGENT_GRANT_TTL_CEILING_MS)
113
+ throw new Error("agent-login: grant expiry exceeds the ceiling");
114
+ return { grant: result.grant, expires_at: result.expires_at };
115
+ }
116
+ /**
117
+ * Strictly validate the exchange/refresh success body (closed keys + RFC3339).
118
+ * `now` is injected so validation is deterministic: a freshly issued session MUST
119
+ * have a strictly-future access expiry (and refresh expiry, when present) — otherwise
120
+ * we would persist an already-dead session that the very next request must refresh.
121
+ */
122
+ export function parseAgentSession(body, now) {
123
+ if (!body || typeof body !== "object")
124
+ throw new Error("agent-login: exchange response is not an object");
125
+ if (!hasExactKeys(body, ["schema", "token_type", "access_token", "access_expires_at", "refresh_token", "refresh_expires_at"])) {
126
+ throw new Error("agent-login: session has unexpected fields");
127
+ }
128
+ if (body.schema !== "raft-cli-agent-session.v1")
129
+ throw new Error("agent-login: unexpected session schema");
130
+ if (body.token_type !== "Bearer")
131
+ throw new Error("agent-login: unexpected token_type");
132
+ for (const k of ["access_token", "refresh_token"]) {
133
+ if (typeof body[k] !== "string" || body[k].length === 0)
134
+ throw new Error(`agent-login: session missing ${k}`);
135
+ }
136
+ const accessExp = parseRfc3339(body.access_expires_at);
137
+ if (accessExp === null)
138
+ throw new Error("agent-login: session access_expires_at is not RFC3339");
139
+ if (accessExp <= now)
140
+ throw new Error("agent-login: session access token is already expired");
141
+ if (body.refresh_expires_at !== null) {
142
+ const refreshExp = parseRfc3339(body.refresh_expires_at);
143
+ if (refreshExp === null)
144
+ throw new Error("agent-login: session refresh_expires_at must be RFC3339 or null");
145
+ if (refreshExp <= now)
146
+ throw new Error("agent-login: session refresh token is already expired");
147
+ }
148
+ return body;
149
+ }
150
+ /** mkdir (if needed) + verify/repair 0700 (no group/other) on one path component. */
151
+ function ensureSecureDir(dir) {
152
+ try {
153
+ mkdirSync(dir, { mode: 0o700 });
154
+ }
155
+ catch (e) {
156
+ if (e?.code !== "EEXIST")
157
+ throw e;
158
+ }
159
+ const st = statSync(dir);
160
+ if (!st.isDirectory())
161
+ throw new Error("agent-login: store path component is not a directory");
162
+ if ((st.mode & 0o077) !== 0)
163
+ chmodSync(dir, 0o700); // repair a pre-existing wide dir
164
+ }
165
+ /**
166
+ * Atomic, hardened store write: O_EXCL unique temp in the same dir, 0600, write +
167
+ * fsync + close, atomic rename. Each dir component under $SLOCK_HOME is ensured AND
168
+ * verified 0700 (repairing a pre-existing wide dir). $SLOCK_HOME itself is not chmod'd.
169
+ * On any failure the temp is removed and the previous file is left intact.
170
+ */
171
+ export function writeAgentSession(a, service, session, apiBase, now = () => new Date().toISOString()) {
172
+ const path = agentAuthPath(a, service); // validates slug + agent id + containment
173
+ let dir = a.slockHome;
174
+ for (const seg of ["agents", a.agentId, "integrations", service]) {
175
+ dir = join(dir, seg);
176
+ ensureSecureDir(dir);
177
+ }
178
+ const record = { ...session, service, api_base: apiBase, updated_at: now() };
179
+ const payload = JSON.stringify(record, null, 2) + "\n";
180
+ const tmp = join(dir, `.auth.${randomBytes(8).toString("hex")}.tmp`);
181
+ let fd = null;
182
+ try {
183
+ fd = openSync(tmp, "wx", 0o600); // 'wx' = O_CREAT|O_EXCL|O_WRONLY
184
+ writeSync(fd, payload);
185
+ fsyncSync(fd);
186
+ closeSync(fd);
187
+ fd = null;
188
+ renameSync(tmp, path);
189
+ }
190
+ catch (e) {
191
+ if (fd !== null) {
192
+ try {
193
+ closeSync(fd);
194
+ }
195
+ catch { /* ignore */ }
196
+ }
197
+ try {
198
+ rmSync(tmp, { force: true });
199
+ }
200
+ catch { /* ignore */ }
201
+ throw e; // previous auth.json (if any) is left intact
202
+ }
203
+ return path;
204
+ }
205
+ // Token responses are small JSON; cap the read so a hostile/broken endpoint cannot
206
+ // stream an unbounded body. Shared by the exchange and refresh token requests.
207
+ export const MAX_TOKEN_RESPONSE_BYTES = 64 * 1024;
208
+ /**
209
+ * Read a response body with a hard byte cap. If an AbortController is supplied it is
210
+ * aborted when the cap is exceeded (so a still-open connection is torn down, and — in
211
+ * `rotate` — the same controller's deadline keeps covering this read). Falls back to
212
+ * `.text()` for response doubles that expose no stream (still cap-checked).
213
+ */
214
+ export async function readBoundedText(res, controller) {
215
+ const declared = Number(res.headers?.get?.("content-length"));
216
+ if (Number.isFinite(declared) && declared > MAX_TOKEN_RESPONSE_BYTES) {
217
+ controller?.abort();
218
+ throw new Error("agent-login: token response exceeds the size limit");
219
+ }
220
+ const reader = res.body?.getReader?.();
221
+ if (!reader) {
222
+ const t = await res.text();
223
+ if (t.length > MAX_TOKEN_RESPONSE_BYTES)
224
+ throw new Error("agent-login: token response exceeds the size limit");
225
+ return t;
226
+ }
227
+ const chunks = [];
228
+ let total = 0;
229
+ for (;;) {
230
+ const { done, value } = await reader.read();
231
+ if (done)
232
+ break;
233
+ if (value) {
234
+ total += value.byteLength;
235
+ if (total > MAX_TOKEN_RESPONSE_BYTES) {
236
+ controller?.abort();
237
+ try {
238
+ await reader.cancel();
239
+ }
240
+ catch { /* ignore */ }
241
+ throw new Error("agent-login: token response exceeds the size limit");
242
+ }
243
+ chunks.push(value);
244
+ }
245
+ }
246
+ const out = new Uint8Array(total);
247
+ let off = 0;
248
+ for (const c of chunks) {
249
+ out.set(c, off);
250
+ off += c.byteLength;
251
+ }
252
+ return new TextDecoder().decode(out);
253
+ }
254
+ function defaultInvoke(raftBin, args) {
255
+ const res = spawnSync(raftBin, args, { encoding: "utf8" });
256
+ return {
257
+ status: res.error ? null : res.status,
258
+ stdout: res.stdout ?? "",
259
+ stderr: res.stderr ?? "",
260
+ };
261
+ }
262
+ /**
263
+ * Full agent-login flow: invoke the pinned wrapper → strict-validate grant → exchange
264
+ * → strict-validate session → atomic store. Returns the stored session on success.
265
+ */
266
+ export async function runAgentLogin(a, opts = {}) {
267
+ const service = opts.service ?? HANDS_SERVICE;
268
+ const now = opts.now ?? Date.now();
269
+ const { verifier, challenge } = generatePkce();
270
+ const args = [
271
+ "integration", "invoke",
272
+ "--service", service,
273
+ "--action", "agent-login",
274
+ "--json",
275
+ "--data-json", JSON.stringify({
276
+ schema: "raft-cli-agent-login-request.v1",
277
+ code_challenge: challenge,
278
+ code_challenge_method: "S256",
279
+ }),
280
+ ];
281
+ const runner = opts.invoke ?? ((a2) => defaultInvoke(a.raftBin, a2));
282
+ const res = runner(args);
283
+ if (res.status !== 0) {
284
+ // Require a clean exit; never echo stdout/stderr (may carry grant/action payload).
285
+ throw new Error(`agent-login: raft invoke exited with a non-zero status (${res.status ?? "spawn error"})`);
286
+ }
287
+ const { grant } = parseAgentLoginInvoke(res.stdout, service, now);
288
+ // Independent token request: NO stored Bearer, NO auto-refresh. `hands login` is the
289
+ // recovery path when the stored refresh has reached a terminal state
290
+ // (expired/reused/revoked); routing this exchange through the api client would first
291
+ // try to refresh that dead token and throw before the fresh grant is ever spent.
292
+ const apiBase = getApiBase();
293
+ const fetchImpl = opts.fetchImpl ?? fetch;
294
+ const exchangeRes = await fetchImpl(new URL("/api/auth/agent/exchange", apiBase).toString(), {
295
+ method: "POST",
296
+ headers: { "content-type": "application/json", accept: "application/json" },
297
+ body: JSON.stringify({ schema: "raft-cli-agent-login-exchange.v1", grant, code_verifier: verifier }),
298
+ // Never follow a redirect: a 307/308 would forward the grant + code_verifier body
299
+ // to the redirect target. `manual` leaves a 3xx as a non-ok status we reject below.
300
+ redirect: "manual",
301
+ });
302
+ if (!exchangeRes.ok) {
303
+ // Stable reason only; never echo the response body (may carry token material).
304
+ throw new Error(`agent-login: grant exchange failed (HTTP ${exchangeRes.status})`);
305
+ }
306
+ const exchangeText = await readBoundedText(exchangeRes);
307
+ let exchangeBody;
308
+ try {
309
+ exchangeBody = JSON.parse(exchangeText);
310
+ }
311
+ catch {
312
+ throw new Error("agent-login: exchange response was not JSON");
313
+ }
314
+ const session = parseAgentSession(exchangeBody, now);
315
+ writeAgentSession(a, service, session, apiBase);
316
+ return session;
317
+ }
318
+ //# sourceMappingURL=agent_auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent_auth.js","sourceRoot":"","sources":["../../src/lib/agent_auth.ts"],"names":[],"mappings":"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"}