@zeroxyz/cli 1.29.0 → 1.29.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.
Files changed (2) hide show
  1. package/dist/index.js +119 -31
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -170257,7 +170257,7 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
170257
170257
 
170258
170258
  // package.json
170259
170259
  var package_default2 = {
170260
- version: "1.29.0"};
170260
+ version: "1.29.1"};
170261
170261
 
170262
170262
  // src/app.ts
170263
170263
  init_esm_shims();
@@ -170915,6 +170915,7 @@ var getConfigPath = () => join$1(homedir(), ".zero", "config.json");
170915
170915
  var CLAIM_NOT_CONFIRMED_RETRIES = 12;
170916
170916
  var CLAIM_NOT_CONFIRMED_INTERVAL_S = 5;
170917
170917
  var CONSENT_POLL_INTERVAL_S = 3;
170918
+ var FINISH_CONSENT_WAIT_MS = 6e4;
170918
170919
  var ASSERTION_EXPIRY_MARGIN_MS = 6e4;
170919
170920
  var sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
170920
170921
  var normalizeUrl = (raw) => {
@@ -171056,10 +171057,21 @@ var authIdentityCommand = (appContext) => new Command("identity").description(
171056
171057
  ).argument("<url>", "The service host, or any URL on it").option(
171057
171058
  "--claim-code <code>",
171058
171059
  "Finish an interaction_required claim with the pairing code the account owner read off the claim page"
171060
+ ).option(
171061
+ "--start",
171062
+ "Never wait on consent: if the user's approval is needed, print the approval link and exit (pair with --finish); otherwise proceed straight to the token. Default when stdin is not a TTY."
171063
+ ).option(
171064
+ "--finish",
171065
+ "Complete a sign-in begun with --start: wait for the user's consent decision (up to a minute per run \u2014 re-run to keep waiting), then print the bearer token."
171059
171066
  ).option("--json", "Emit machine-readable JSON instead of human text").action(
171060
171067
  async (rawUrl, opts) => {
171061
171068
  const { client, analyticsService } = appContext.services;
171062
171069
  const json3 = opts.json ?? false;
171070
+ if (opts.start && opts.finish) {
171071
+ process.stderr.write("Pass either --start or --finish, not both.\n");
171072
+ process.exitCode = 1;
171073
+ return;
171074
+ }
171063
171075
  const target = normalizeUrl(rawUrl);
171064
171076
  if (!target) {
171065
171077
  process.stderr.write(`Not a valid URL or host: ${rawUrl}
@@ -171163,41 +171175,110 @@ This host does not appear to support agent auth. If it serves an /auth.md, follo
171163
171175
  return;
171164
171176
  }
171165
171177
  if (outcome.status === "consent_required") {
171166
- const requested = await client.auth.identity.requestGrant({
171167
- audience: discovery.mintAudience,
171168
- resourceUrl: target.origin
171169
- }).catch((err) => {
171170
- process.stderr.write(
171171
- `Could not create the consent request: ${truncateError(err instanceof Error ? err.message : String(err))}
171178
+ const storedConsent = readConfig(getConfigPath()).serviceIdentities?.[host]?.pendingConsent;
171179
+ let pending = storedConsent && (!storedConsent.expiresAt || Date.parse(storedConsent.expiresAt) > Date.now()) ? storedConsent : null;
171180
+ if (!pending) {
171181
+ const requested = await client.auth.identity.requestGrant({
171182
+ audience: discovery.mintAudience,
171183
+ resourceUrl: target.origin
171184
+ }).catch((err) => {
171185
+ process.stderr.write(
171186
+ `Could not create the consent request: ${truncateError(err instanceof Error ? err.message : String(err))}
171172
171187
  `
171173
- );
171174
- return null;
171175
- });
171176
- if (!requested) {
171177
- capture("error");
171178
- process.exitCode = 1;
171188
+ );
171189
+ return null;
171190
+ });
171191
+ if (!requested) {
171192
+ capture("error");
171193
+ process.exitCode = 1;
171194
+ return;
171195
+ }
171196
+ pending = {
171197
+ requestId: requested.requestId,
171198
+ approveUrl: requested.approveUrl,
171199
+ expiresAt: requested.expiresAt
171200
+ };
171201
+ const next = pending;
171202
+ updateServiceIdentity(host, (current) => ({
171203
+ ...current,
171204
+ pendingConsent: next
171205
+ }));
171206
+ }
171207
+ const waitsInline = opts.finish || !opts.start && process.stdin.isTTY;
171208
+ if (!waitsInline) {
171209
+ capture("consent_started");
171210
+ if (json3) {
171211
+ process.stdout.write(
171212
+ `${JSON.stringify({
171213
+ status: "consent_required",
171214
+ approveUrl: pending.approveUrl,
171215
+ expiresAt: pending.expiresAt,
171216
+ next: `Send the user to approveUrl. Then run \`zero auth identity ${host} --finish\` \u2014 it waits for their decision and prints the bearer token.`
171217
+ })}
171218
+ `
171219
+ );
171220
+ } else {
171221
+ process.stderr.write(
171222
+ [
171223
+ "",
171224
+ `Signing in to ${discovery.resourceName ?? host} needs the user's one-time consent.`,
171225
+ `Send them here to approve: ${pending.approveUrl}`,
171226
+ `(valid until ${pending.expiresAt}; the decision is remembered on their Zero account)`,
171227
+ "",
171228
+ `Then run: zero auth identity ${host} --finish`,
171229
+ "It waits for their decision and prints the bearer token.",
171230
+ ""
171231
+ ].join("\n")
171232
+ );
171233
+ }
171179
171234
  return;
171180
171235
  }
171181
171236
  process.stderr.write(
171182
171237
  [
171183
171238
  "",
171184
171239
  `Signing in to ${discovery.resourceName ?? host} needs the user's one-time consent.`,
171185
- `Send them here to approve: ${requested.approveUrl}`,
171186
- `(valid until ${requested.expiresAt}; the decision is remembered on their Zero account)`,
171240
+ `Send them here to approve: ${pending.approveUrl}`,
171241
+ `(valid until ${pending.expiresAt}; the decision is remembered on their Zero account)`,
171187
171242
  "Waiting for their decision\u2026"
171188
171243
  ].join("\n")
171189
171244
  );
171190
- let decision = "expired";
171245
+ const deadline = opts.finish ? Date.now() + FINISH_CONSENT_WAIT_MS : null;
171246
+ let decision = "pending";
171191
171247
  for (; ; ) {
171192
- const status = await client.auth.identity.grantRequest(requested.requestId).catch(() => null);
171248
+ const status = await client.auth.identity.grantRequest(pending.requestId).catch(() => null);
171193
171249
  if (status && status.status !== "pending") {
171194
171250
  decision = status.status;
171195
171251
  break;
171196
171252
  }
171253
+ if (deadline !== null && Date.now() >= deadline) break;
171197
171254
  process.stderr.write(".");
171198
171255
  await sleep2(CONSENT_POLL_INTERVAL_S * 1e3);
171199
171256
  }
171200
171257
  process.stderr.write("\n");
171258
+ if (decision === "pending") {
171259
+ capture("consent_pending");
171260
+ if (json3) {
171261
+ process.stdout.write(
171262
+ `${JSON.stringify({
171263
+ status: "pending",
171264
+ approveUrl: pending.approveUrl,
171265
+ expiresAt: pending.expiresAt,
171266
+ next: `The user has not decided yet. Re-run \`zero auth identity ${host} --finish\` to keep waiting.`
171267
+ })}
171268
+ `
171269
+ );
171270
+ } else {
171271
+ process.stderr.write(
171272
+ `No decision yet. Re-run \`zero auth identity ${host} --finish\` to keep waiting.
171273
+ `
171274
+ );
171275
+ }
171276
+ return;
171277
+ }
171278
+ updateServiceIdentity(
171279
+ host,
171280
+ ({ pendingConsent: _drop, ...rest }) => rest
171281
+ );
171201
171282
  if (decision === "denied") {
171202
171283
  capture("consent_denied");
171203
171284
  process.stderr.write(
@@ -171230,20 +171311,27 @@ This host does not appear to support agent auth. If it serves an /auth.md, follo
171230
171311
  }
171231
171312
  switch (outcome.status) {
171232
171313
  case "ok": {
171233
- updateServiceIdentity(host, ({ pendingClaim: _drop, ...rest }) => ({
171234
- ...rest,
171235
- registrationId: outcome.registration.registrationId,
171236
- assertion: outcome.registration.identityAssertion,
171237
- ...outcome.registration.assertionExpires && {
171238
- assertionExpires: outcome.registration.assertionExpires
171239
- },
171240
- ...outcome.registration.refreshToken && {
171241
- refreshToken: outcome.registration.refreshToken
171242
- },
171243
- ...discovery.resourceName && {
171244
- resourceName: discovery.resourceName
171245
- }
171246
- }));
171314
+ updateServiceIdentity(
171315
+ host,
171316
+ ({
171317
+ pendingClaim: _dropClaim,
171318
+ pendingConsent: _drop,
171319
+ ...rest
171320
+ }) => ({
171321
+ ...rest,
171322
+ registrationId: outcome.registration.registrationId,
171323
+ assertion: outcome.registration.identityAssertion,
171324
+ ...outcome.registration.assertionExpires && {
171325
+ assertionExpires: outcome.registration.assertionExpires
171326
+ },
171327
+ ...outcome.registration.refreshToken && {
171328
+ refreshToken: outcome.registration.refreshToken
171329
+ },
171330
+ ...discovery.resourceName && {
171331
+ resourceName: discovery.resourceName
171332
+ }
171333
+ })
171334
+ );
171247
171335
  const ok = await exchangeAndEmit(
171248
171336
  client,
171249
171337
  discovery,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.29.0",
3
+ "version": "1.29.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",