@zeroxyz/cli 1.28.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 +937 -102
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -62738,10 +62738,10 @@ var require_provider_etherscan = __commonJS({
62738
62738
  *
62739
62739
  * If %%post%%, the request is made as a POST request.
62740
62740
  */
62741
- async fetch(module2, params, post) {
62741
+ async fetch(module2, params, post2) {
62742
62742
  const id = nextId++;
62743
- const url4 = post ? this.getPostUrl() : this.getUrl(module2, params);
62744
- const payload = post ? this.getPostData(module2, params) : null;
62743
+ const url4 = post2 ? this.getPostUrl() : this.getUrl(module2, params);
62744
+ const payload = post2 ? this.getPostData(module2, params) : null;
62745
62745
  this.emit("debug", { action: "sendRequest", id, url: url4, payload });
62746
62746
  const request3 = new index_js_4.FetchRequest(url4);
62747
62747
  request3.setThrottleParams({ slotInterval: 1e3 });
@@ -78668,7 +78668,7 @@ init_esm_shims();
78668
78668
  // ../sdk/dist/index.js
78669
78669
  init_esm_shims();
78670
78670
 
78671
- // ../sdk/dist/chunk-PLDXIESP.js
78671
+ // ../sdk/dist/chunk-5334O6ZN.js
78672
78672
  init_esm_shims();
78673
78673
 
78674
78674
  // ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
@@ -164365,7 +164365,7 @@ var redactUrl = (raw) => {
164365
164365
  };
164366
164366
  var truncateError = (raw) => raw.length > ERROR_MAX ? `${raw.slice(0, ERROR_MAX)}\u2026` : raw;
164367
164367
  var package_default = {
164368
- version: "0.21.0"
164368
+ version: "0.22.0"
164369
164369
  };
164370
164370
  var SDK_VERSION2 = package_default.version;
164371
164371
  var ZeroError = class extends Error {
@@ -167660,7 +167660,6 @@ var agentZeroSessionSchema = external_exports3.object({
167660
167660
  user: external_exports3.object({ id: external_exports3.string() }).loose(),
167661
167661
  walletAddress: external_exports3.string().optional()
167662
167662
  }).loose();
167663
- var JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
167664
167663
  var trimSlash = (value) => value.replace(/\/$/, "");
167665
167664
  var wrapNetworkError = (url4, err) => {
167666
167665
  const cause = err?.cause;
@@ -167670,6 +167669,80 @@ var wrapNetworkError = (url4, err) => {
167670
167669
  cause: err
167671
167670
  });
167672
167671
  };
167672
+ var getJson = async (fetchImpl, url4) => {
167673
+ const response = await fetchImpl(url4).catch((err) => {
167674
+ throw wrapNetworkError(url4, err);
167675
+ });
167676
+ if (!response.ok) {
167677
+ throw new ZeroAgentAuthError(`GET ${url4} failed (${response.status})`, {
167678
+ status: response.status
167679
+ });
167680
+ }
167681
+ return await response.json();
167682
+ };
167683
+ var postJson = (fetchImpl, url4, body, schema) => post(fetchImpl, url4, "application/json", JSON.stringify(body), schema);
167684
+ var postForm = (fetchImpl, url4, fields, schema) => post(
167685
+ fetchImpl,
167686
+ url4,
167687
+ "application/x-www-form-urlencoded",
167688
+ new URLSearchParams(fields).toString(),
167689
+ schema
167690
+ );
167691
+ var post = async (fetchImpl, url4, contentType, body, schema) => {
167692
+ const response = await fetchImpl(url4, {
167693
+ method: "POST",
167694
+ headers: { "content-type": contentType },
167695
+ body
167696
+ }).catch((err) => {
167697
+ throw wrapNetworkError(url4, err);
167698
+ });
167699
+ const text = await response.text();
167700
+ let parsed = null;
167701
+ try {
167702
+ parsed = text ? JSON.parse(text) : null;
167703
+ } catch {
167704
+ }
167705
+ if (!response.ok) {
167706
+ const errBody = parsed;
167707
+ const code = errBody?.code ?? errBody?.error;
167708
+ throw new ZeroAgentAuthError(
167709
+ `Agent auth request to ${url4} failed (${response.status}${typeof code === "string" ? `: ${code}` : ""})`,
167710
+ { status: response.status, body: parsed ?? text }
167711
+ );
167712
+ }
167713
+ return schema.parse(parsed);
167714
+ };
167715
+ var completeClaimAt = async (fetchImpl, claimEndpoint, input) => {
167716
+ try {
167717
+ const identity = await postJson(
167718
+ fetchImpl,
167719
+ `${claimEndpoint}/complete`,
167720
+ { claim_token: input.claimToken, user_code: input.userCode },
167721
+ completeClaimResponseSchema
167722
+ );
167723
+ return { status: "ok", ...identity };
167724
+ } catch (err) {
167725
+ if (err instanceof ZeroAgentAuthError && err.serverCode) {
167726
+ if (err.serverCode === "claim_not_confirmed") {
167727
+ return { status: "not_confirmed" };
167728
+ }
167729
+ if (err.serverCode === "invalid_user_code") {
167730
+ return { status: "invalid_code" };
167731
+ }
167732
+ if ([
167733
+ "user_code_expired",
167734
+ "claim_expired",
167735
+ "claim_revoked",
167736
+ "already_claimed",
167737
+ "claim_denied"
167738
+ ].includes(err.serverCode)) {
167739
+ return { status: "expired", code: err.serverCode };
167740
+ }
167741
+ }
167742
+ throw err;
167743
+ }
167744
+ };
167745
+ var JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
167673
167746
  var AuthAgent = class {
167674
167747
  constructor(client) {
167675
167748
  this.client = client;
@@ -167687,7 +167760,8 @@ var AuthAgent = class {
167687
167760
  };
167688
167761
  register = async () => {
167689
167762
  const endpoints = await this.endpoints();
167690
- return this.postJson(
167763
+ return postJson(
167764
+ this.client.fetchImpl,
167691
167765
  endpoints.identityEndpoint,
167692
167766
  { type: "anonymous" },
167693
167767
  identityEnvelopeSchema
@@ -167695,7 +167769,8 @@ var AuthAgent = class {
167695
167769
  };
167696
167770
  exchangeAssertion = async (identityAssertion) => {
167697
167771
  const endpoints = await this.endpoints();
167698
- return this.postForm(
167772
+ return postForm(
167773
+ this.client.fetchImpl,
167699
167774
  endpoints.tokenEndpoint,
167700
167775
  { grant_type: JWT_BEARER_GRANT_TYPE, assertion: identityAssertion },
167701
167776
  agentTokenResponseSchema
@@ -167725,7 +167800,8 @@ var AuthAgent = class {
167725
167800
  { status: 0 }
167726
167801
  );
167727
167802
  }
167728
- return this.postJson(
167803
+ return postJson(
167804
+ this.client.fetchImpl,
167729
167805
  endpoints.claimEndpoint,
167730
167806
  {
167731
167807
  type: "service_auth",
@@ -167735,8 +167811,6 @@ var AuthAgent = class {
167735
167811
  startClaimResponseSchema
167736
167812
  );
167737
167813
  };
167738
- // Submit the pairing code the human read off the hosted page. Terminal
167739
- // states map to a typed result; anything unexpected throws.
167740
167814
  completeClaim = async (input) => {
167741
167815
  const endpoints = await this.endpoints();
167742
167816
  if (!endpoints.claimEndpoint) {
@@ -167745,33 +167819,10 @@ var AuthAgent = class {
167745
167819
  { status: 0 }
167746
167820
  );
167747
167821
  }
167748
- try {
167749
- const identity = await this.postJson(
167750
- `${endpoints.claimEndpoint}/complete`,
167751
- { claim_token: input.claimToken, user_code: input.userCode },
167752
- completeClaimResponseSchema
167753
- );
167754
- return { status: "ok", ...identity };
167755
- } catch (err) {
167756
- if (err instanceof ZeroAgentAuthError && err.serverCode) {
167757
- if (err.serverCode === "claim_not_confirmed") {
167758
- return { status: "not_confirmed" };
167759
- }
167760
- if (err.serverCode === "invalid_user_code") {
167761
- return { status: "invalid_code" };
167762
- }
167763
- if ([
167764
- "user_code_expired",
167765
- "claim_expired",
167766
- "claim_revoked",
167767
- "already_claimed",
167768
- "claim_denied"
167769
- ].includes(err.serverCode)) {
167770
- return { status: "expired", code: err.serverCode };
167771
- }
167772
- }
167773
- throw err;
167774
- }
167822
+ return completeClaimAt(this.client.fetchImpl, endpoints.claimEndpoint, {
167823
+ claimToken: input.claimToken,
167824
+ userCode: input.userCode
167825
+ });
167775
167826
  };
167776
167827
  // Resolve (and cache) the agent-auth endpoints via discovery.
167777
167828
  endpoints = () => {
@@ -167784,13 +167835,15 @@ var AuthAgent = class {
167784
167835
  return this.endpointsPromise;
167785
167836
  };
167786
167837
  discover = async () => {
167787
- const resource = await this.getJson(
167838
+ const resource = await getJson(
167839
+ this.client.fetchImpl,
167788
167840
  `${trimSlash(this.client.baseUrl)}/.well-known/oauth-protected-resource`
167789
167841
  );
167790
167842
  let lastError = null;
167791
167843
  for (const server of resource.authorization_servers ?? []) {
167792
167844
  try {
167793
- const raw = await this.getJson(
167845
+ const raw = await getJson(
167846
+ this.client.fetchImpl,
167794
167847
  `${trimSlash(server)}/.well-known/oauth-authorization-server`
167795
167848
  );
167796
167849
  const metadata = agentAuthMetadataSchema.parse(raw);
@@ -167809,48 +167862,6 @@ var AuthAgent = class {
167809
167862
  { status: 0, cause: lastError }
167810
167863
  );
167811
167864
  };
167812
- getJson = async (url4) => {
167813
- const response = await this.client.fetchImpl(url4).catch((err) => {
167814
- throw wrapNetworkError(url4, err);
167815
- });
167816
- if (!response.ok) {
167817
- throw new ZeroAgentAuthError(`GET ${url4} failed (${response.status})`, {
167818
- status: response.status
167819
- });
167820
- }
167821
- return await response.json();
167822
- };
167823
- postJson = (url4, body, schema) => this.post(url4, "application/json", JSON.stringify(body), schema);
167824
- postForm = (url4, fields, schema) => this.post(
167825
- url4,
167826
- "application/x-www-form-urlencoded",
167827
- new URLSearchParams(fields).toString(),
167828
- schema
167829
- );
167830
- post = async (url4, contentType, body, schema) => {
167831
- const response = await this.client.fetchImpl(url4, {
167832
- method: "POST",
167833
- headers: { "content-type": contentType },
167834
- body
167835
- }).catch((err) => {
167836
- throw wrapNetworkError(url4, err);
167837
- });
167838
- const text = await response.text();
167839
- let parsed = null;
167840
- try {
167841
- parsed = text ? JSON.parse(text) : null;
167842
- } catch {
167843
- }
167844
- if (!response.ok) {
167845
- const errBody = parsed;
167846
- const code = errBody?.code ?? errBody?.error;
167847
- throw new ZeroAgentAuthError(
167848
- `Agent auth request to ${url4} failed (${response.status}${typeof code === "string" ? `: ${code}` : ""})`,
167849
- { status: response.status, body: parsed ?? text }
167850
- );
167851
- }
167852
- return schema.parse(parsed);
167853
- };
167854
167865
  };
167855
167866
  var userWalletDtoSchema = external_exports3.object({
167856
167867
  walletAddress: external_exports3.string(),
@@ -167961,6 +167972,294 @@ var AuthDevice = class {
167961
167972
  };
167962
167973
  };
167963
167974
  };
167975
+ var ID_JAG_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:id-jag";
167976
+ var idJagMintResponseSchema = external_exports3.object({
167977
+ access_token: external_exports3.string(),
167978
+ issued_token_type: external_exports3.string().optional(),
167979
+ expires_in: external_exports3.number().optional()
167980
+ }).loose().transform((raw) => ({
167981
+ idJag: raw.access_token,
167982
+ issuedTokenType: raw.issued_token_type ?? ID_JAG_TOKEN_TYPE,
167983
+ expiresIn: raw.expires_in ?? null
167984
+ }));
167985
+ var protectedResourceMetadataSchema = external_exports3.object({
167986
+ resource: external_exports3.string().optional(),
167987
+ resource_name: external_exports3.string().optional(),
167988
+ authorization_servers: external_exports3.array(external_exports3.string()).optional()
167989
+ }).loose();
167990
+ var serviceAuthMetadataSchema = external_exports3.object({
167991
+ resource: external_exports3.string().optional(),
167992
+ resource_name: external_exports3.string().optional(),
167993
+ token_endpoint: external_exports3.string().optional(),
167994
+ agent_auth: external_exports3.object({
167995
+ identity_endpoint: external_exports3.string(),
167996
+ claim_endpoint: external_exports3.string().optional(),
167997
+ identity_types_supported: external_exports3.array(external_exports3.string()).optional(),
167998
+ identity_assertion: external_exports3.object({
167999
+ assertion_types_supported: external_exports3.array(external_exports3.string()).optional(),
168000
+ // Optional shared-audience hint: a platform fronting many
168001
+ // storefronts advertises one audience (its AS) so a single
168002
+ // consent covers the network.
168003
+ audience: external_exports3.string().optional()
168004
+ }).loose().optional()
168005
+ }).loose()
168006
+ }).loose();
168007
+ var identityAssertionEnvelopeSchema = external_exports3.object({
168008
+ id: external_exports3.string(),
168009
+ identity: external_exports3.object({
168010
+ assertion: external_exports3.string(),
168011
+ expires_at: external_exports3.string().optional(),
168012
+ refresh_token: external_exports3.object({ value: external_exports3.string() }).loose().optional()
168013
+ }).loose(),
168014
+ assertion_expires: external_exports3.string().nullable().optional()
168015
+ }).loose().transform((raw) => ({
168016
+ registrationId: raw.id,
168017
+ identityAssertion: raw.identity.assertion,
168018
+ assertionExpires: raw.assertion_expires ?? raw.identity.expires_at ?? null,
168019
+ refreshToken: raw.identity.refresh_token?.value ?? null
168020
+ }));
168021
+ var interactionRequiredBodySchema = external_exports3.object({
168022
+ error_description: external_exports3.string().optional(),
168023
+ claim: external_exports3.object({
168024
+ token: external_exports3.string().optional(),
168025
+ expires_at: external_exports3.string().optional(),
168026
+ attempt: external_exports3.object({
168027
+ verification_uri: external_exports3.string().optional(),
168028
+ expires_at: external_exports3.string().optional()
168029
+ }).loose().optional()
168030
+ }).loose().optional()
168031
+ }).loose();
168032
+ var identityGrantSchema = external_exports3.object({ audience: external_exports3.string(), createdAt: external_exports3.string() }).loose();
168033
+ var identityGrantListSchema = external_exports3.object({ grants: external_exports3.array(identityGrantSchema) }).loose();
168034
+ var identityGrantRevokeSchema = external_exports3.object({ revoked: external_exports3.boolean() }).loose();
168035
+ var identityGrantRequestSchema = external_exports3.object({
168036
+ requestId: external_exports3.string(),
168037
+ approveUrl: external_exports3.string(),
168038
+ expiresAt: external_exports3.string()
168039
+ }).loose();
168040
+ var identityGrantRequestStatusSchema = external_exports3.object({
168041
+ requestId: external_exports3.string(),
168042
+ status: external_exports3.enum(["pending", "approved", "denied", "expired"]),
168043
+ audience: external_exports3.string(),
168044
+ resourceName: external_exports3.string().nullable().optional()
168045
+ }).loose();
168046
+ var TOKEN_EXCHANGE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange";
168047
+ var SUBJECT_TOKEN_TYPE_ACCESS_TOKEN = "urn:ietf:params:oauth:token-type:access_token";
168048
+ var JWT_BEARER_GRANT_TYPE2 = "urn:ietf:params:oauth:grant-type:jwt-bearer";
168049
+ var IDENTITY_ASSERTION_TYPE = "identity_assertion";
168050
+ var AuthIdentity = class {
168051
+ constructor(client) {
168052
+ this.client = client;
168053
+ }
168054
+ discover = async (url4) => {
168055
+ const origin2 = new URL(url4).origin;
168056
+ const prm = protectedResourceMetadataSchema.parse(
168057
+ await getJson(
168058
+ this.client.fetchImpl,
168059
+ `${origin2}/.well-known/oauth-protected-resource`
168060
+ )
168061
+ );
168062
+ let lastError = null;
168063
+ for (const server of prm.authorization_servers ?? [origin2]) {
168064
+ try {
168065
+ const metadata = serviceAuthMetadataSchema.parse(
168066
+ await getJson(
168067
+ this.client.fetchImpl,
168068
+ `${trimSlash(server)}/.well-known/oauth-authorization-server`
168069
+ )
168070
+ );
168071
+ const agentAuth = metadata.agent_auth;
168072
+ const assertionTypes = agentAuth.identity_assertion?.assertion_types_supported;
168073
+ const resource = prm.resource ?? `${origin2}/`;
168074
+ return {
168075
+ resource,
168076
+ mintAudience: agentAuth.identity_assertion?.audience ?? resource,
168077
+ resourceName: prm.resource_name ?? metadata.resource_name ?? null,
168078
+ authorizationServer: trimSlash(server),
168079
+ identityEndpoint: agentAuth.identity_endpoint,
168080
+ claimEndpoint: agentAuth.claim_endpoint ?? null,
168081
+ tokenEndpoint: metadata.token_endpoint ?? `${trimSlash(server)}/oauth2/token`,
168082
+ identityAssertionSupported: (agentAuth.identity_types_supported ?? []).includes(
168083
+ IDENTITY_ASSERTION_TYPE
168084
+ ) && (assertionTypes ? assertionTypes.includes(ID_JAG_TOKEN_TYPE) : true)
168085
+ };
168086
+ } catch (err) {
168087
+ lastError = err;
168088
+ }
168089
+ }
168090
+ throw new ZeroAgentAuthError(
168091
+ `No authorization server with an agent_auth block found at ${origin2} \u2014 agent auth is not enabled for this service.`,
168092
+ { status: 0, cause: lastError }
168093
+ );
168094
+ };
168095
+ // The minted grant is single-use (fresh jti) and minutes-lived — mint per
168096
+ // registration, never cache.
168097
+ mint = async (input) => {
168098
+ const attempt = () => {
168099
+ const credentials = this.client.getCredentials();
168100
+ if (credentials.kind !== "session") {
168101
+ throw new ZeroAuthError(
168102
+ "auth_no_credentials",
168103
+ "mint() requires session credentials \u2014 the ID-JAG asserts the signed-in user's identity."
168104
+ );
168105
+ }
168106
+ return request2(
168107
+ this.client,
168108
+ {
168109
+ method: "POST",
168110
+ path: "/v1/oauth/token",
168111
+ body: {
168112
+ grant_type: TOKEN_EXCHANGE_GRANT_TYPE,
168113
+ subject_token: credentials.accessToken,
168114
+ subject_token_type: SUBJECT_TOKEN_TYPE_ACCESS_TOKEN,
168115
+ audience: input.audience,
168116
+ requested_token_type: ID_JAG_TOKEN_TYPE
168117
+ }
168118
+ },
168119
+ idJagMintResponseSchema
168120
+ );
168121
+ };
168122
+ try {
168123
+ return await attempt();
168124
+ } catch (err) {
168125
+ if (err instanceof ZeroApiError && err.status === 400 && err.body?.error === "invalid_grant" && await this.client.refreshSessionOnce()) {
168126
+ return await attempt();
168127
+ }
168128
+ throw err;
168129
+ }
168130
+ };
168131
+ // Recoverable protocol states come back as typed outcomes; mint-bug
168132
+ // rejections (invalid_audience, expired, …) throw. replay_detected is
168133
+ // retried once with a freshly minted grant (single-use jti).
168134
+ assert = async (input) => {
168135
+ let discovery;
168136
+ try {
168137
+ discovery = input.discovery ?? await this.discover(input.url);
168138
+ } catch (err) {
168139
+ if (err instanceof ZeroAgentAuthError) {
168140
+ return { status: "unsupported", discovery: null };
168141
+ }
168142
+ throw err;
168143
+ }
168144
+ if (!discovery.identityAssertionSupported) {
168145
+ return { status: "unsupported", discovery };
168146
+ }
168147
+ try {
168148
+ return await this.register(discovery);
168149
+ } catch (err) {
168150
+ if (err instanceof ZeroAgentAuthError && err.serverCode === "replay_detected") {
168151
+ return await this.register(discovery);
168152
+ }
168153
+ throw err;
168154
+ }
168155
+ };
168156
+ // RFC 7523 jwt-bearer. Bearer tokens are minutes-lived: exchange per work
168157
+ // session, persist only the assertion + refresh token.
168158
+ exchange = (input) => postForm(
168159
+ this.client.fetchImpl,
168160
+ input.tokenEndpoint,
168161
+ { grant_type: JWT_BEARER_GRANT_TYPE2, assertion: input.assertion },
168162
+ agentTokenResponseSchema
168163
+ );
168164
+ completeClaim = (input) => completeClaimAt(this.client.fetchImpl, input.claimEndpoint, {
168165
+ claimToken: input.claimToken,
168166
+ userCode: input.userCode
168167
+ });
168168
+ grants = (opts = {}) => request2(
168169
+ this.client,
168170
+ {
168171
+ method: "GET",
168172
+ path: "/v1/users/me/identity-grants",
168173
+ signal: opts.signal
168174
+ },
168175
+ identityGrantListSchema
168176
+ ).then((body) => body.grants);
168177
+ // `resourceUrl` lets the server verify and display the service's
168178
+ // name/logo on the approve page. Poll grantRequest() until decided.
168179
+ requestGrant = (input) => request2(
168180
+ this.client,
168181
+ {
168182
+ method: "POST",
168183
+ path: "/v1/users/me/identity-grants/requests",
168184
+ body: {
168185
+ audience: input.audience,
168186
+ ...input.resourceUrl ? { resourceUrl: input.resourceUrl } : {}
168187
+ }
168188
+ },
168189
+ identityGrantRequestSchema
168190
+ );
168191
+ grantRequest = (requestId, opts = {}) => request2(
168192
+ this.client,
168193
+ {
168194
+ method: "GET",
168195
+ path: `/v1/users/me/identity-grants/requests/${requestId}`,
168196
+ signal: opts.signal
168197
+ },
168198
+ identityGrantRequestStatusSchema
168199
+ );
168200
+ revokeGrant = (input) => request2(
168201
+ this.client,
168202
+ {
168203
+ method: "DELETE",
168204
+ path: "/v1/users/me/identity-grants",
168205
+ query: { audience: input.audience }
168206
+ },
168207
+ identityGrantRevokeSchema
168208
+ ).then((body) => body.revoked);
168209
+ register = async (discovery) => {
168210
+ let minted;
168211
+ try {
168212
+ minted = await this.mint({ audience: discovery.mintAudience });
168213
+ } catch (err) {
168214
+ if (err instanceof ZeroApiError && err.body?.error === "consent_required") {
168215
+ return { status: "consent_required", discovery };
168216
+ }
168217
+ throw err;
168218
+ }
168219
+ try {
168220
+ const registration = await postJson(
168221
+ this.client.fetchImpl,
168222
+ discovery.identityEndpoint,
168223
+ {
168224
+ type: IDENTITY_ASSERTION_TYPE,
168225
+ assertion_type: ID_JAG_TOKEN_TYPE,
168226
+ assertion: minted.idJag
168227
+ },
168228
+ identityAssertionEnvelopeSchema
168229
+ );
168230
+ return { status: "ok", discovery, registration };
168231
+ } catch (err) {
168232
+ if (err instanceof ZeroAgentAuthError) {
168233
+ if (err.serverCode === "issuer_not_enabled") {
168234
+ return { status: "issuer_not_enabled", discovery };
168235
+ }
168236
+ const description = err.body?.error_description;
168237
+ if (err.serverCode === "login_required") {
168238
+ return {
168239
+ status: "login_required",
168240
+ discovery,
168241
+ description: typeof description === "string" ? description : null
168242
+ };
168243
+ }
168244
+ if (err.serverCode === "interaction_required") {
168245
+ const body = interactionRequiredBodySchema.safeParse(err.body);
168246
+ const claim3 = body.success ? body.data.claim : void 0;
168247
+ return {
168248
+ status: "interaction_required",
168249
+ discovery,
168250
+ claim: {
168251
+ claimToken: claim3?.token ?? null,
168252
+ claimTokenExpires: claim3?.expires_at ?? null,
168253
+ verificationUri: claim3?.attempt?.verification_uri ?? null,
168254
+ description: body.success ? body.data.error_description ?? null : null
168255
+ }
168256
+ };
168257
+ }
168258
+ }
168259
+ throw err;
168260
+ }
168261
+ };
168262
+ };
167964
168263
  var userWalletsSchema = external_exports3.array(userWalletDtoSchema);
167965
168264
  var normalizeMessage = (message2) => {
167966
168265
  if (typeof message2 === "string") return message2;
@@ -167992,9 +168291,11 @@ var Auth = class {
167992
168291
  this.client = client;
167993
168292
  this.agent = new AuthAgent(client);
167994
168293
  this.device = new AuthDevice(client);
168294
+ this.identity = new AuthIdentity(client);
167995
168295
  }
167996
168296
  agent;
167997
168297
  device;
168298
+ identity;
167998
168299
  // The internal (web-app facing) user profile. Richer than profile(): full
167999
168300
  // wallet list with per-wallet delegation/signer/limit metadata.
168000
168301
  me = (opts = {}) => request2(
@@ -168537,7 +168838,7 @@ var Runs = class _Runs {
168537
168838
  * target left to name, so that server could never have recorded it.
168538
168839
  */
168539
168840
  create = async (input, opts = {}) => {
168540
- const post = (body) => request2(
168841
+ const post2 = (body) => request2(
168541
168842
  this.client,
168542
168843
  {
168543
168844
  method: "POST",
@@ -168551,7 +168852,7 @@ var Runs = class _Runs {
168551
168852
  let generation = 0;
168552
168853
  for (; ; ) {
168553
168854
  try {
168554
- return await post(payload);
168855
+ return await post2(payload);
168555
168856
  } catch (err) {
168556
168857
  const rejected = err instanceof ZeroApiError && (err.status === 400 || err.status === 422);
168557
168858
  if (!rejected) throw err;
@@ -169956,7 +170257,7 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
169956
170257
 
169957
170258
  // package.json
169958
170259
  var package_default2 = {
169959
- version: "1.28.0"};
170260
+ version: "1.29.1"};
169960
170261
 
169961
170262
  // src/app.ts
169962
170263
  init_esm_shims();
@@ -170608,13 +170909,546 @@ var readConfig = (path3) => {
170608
170909
  }
170609
170910
  };
170610
170911
 
170611
- // src/commands/auth-command.ts
170912
+ // src/commands/auth-identity-command.ts
170913
+ init_esm_shims();
170612
170914
  var getConfigPath = () => join$1(homedir(), ".zero", "config.json");
170915
+ var CLAIM_NOT_CONFIRMED_RETRIES = 12;
170916
+ var CLAIM_NOT_CONFIRMED_INTERVAL_S = 5;
170917
+ var CONSENT_POLL_INTERVAL_S = 3;
170918
+ var FINISH_CONSENT_WAIT_MS = 6e4;
170919
+ var ASSERTION_EXPIRY_MARGIN_MS = 6e4;
170920
+ var sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
170921
+ var normalizeUrl = (raw) => {
170922
+ try {
170923
+ return new URL(/^https?:\/\//.test(raw) ? raw : `https://${raw}`);
170924
+ } catch {
170925
+ return null;
170926
+ }
170927
+ };
170928
+ var updateServiceIdentity = (host, update2) => {
170929
+ const path3 = getConfigPath();
170930
+ ensureSecureDir(dirname(path3));
170931
+ const config3 = readConfig(path3);
170932
+ const identities = { ...config3.serviceIdentities };
170933
+ const next = update2(identities[host] ?? {});
170934
+ if (next === void 0) {
170935
+ delete identities[host];
170936
+ } else {
170937
+ identities[host] = next;
170938
+ }
170939
+ writeSecureFile(
170940
+ path3,
170941
+ JSON.stringify({ ...config3, serviceIdentities: identities }, null, 2)
170942
+ );
170943
+ };
170944
+ var isUsable = (expiresAt) => {
170945
+ if (!expiresAt) return true;
170946
+ const parsed = Date.parse(expiresAt);
170947
+ return Number.isNaN(parsed) ? true : parsed - ASSERTION_EXPIRY_MARGIN_MS > Date.now();
170948
+ };
170949
+ var emitAccessToken = (accessToken, discovery, host, json3, reused) => {
170950
+ if (json3) {
170951
+ process.stdout.write(
170952
+ `${JSON.stringify({
170953
+ status: "ok",
170954
+ accessToken,
170955
+ resource: discovery.resource,
170956
+ resourceName: discovery.resourceName,
170957
+ tokenEndpoint: discovery.tokenEndpoint,
170958
+ reused
170959
+ })}
170960
+ `
170961
+ );
170962
+ return;
170963
+ }
170964
+ process.stderr.write(
170965
+ [
170966
+ `Signed in to ${discovery.resourceName ?? host} with your Zero identity.`,
170967
+ "The bearer token below is short-lived \u2014 use it right away:",
170968
+ ` zero fetch <url> -H "Authorization: Bearer <token>"`,
170969
+ `Re-run this command for a fresh token; it reuses the stored registration.`,
170970
+ ""
170971
+ ].join("\n")
170972
+ );
170973
+ process.stdout.write(`${accessToken}
170974
+ `);
170975
+ };
170976
+ var exchangeAndEmit = async (client, discovery, host, assertion, json3, reused) => {
170977
+ const token = await client.auth.identity.exchange({ tokenEndpoint: discovery.tokenEndpoint, assertion }).catch((err) => {
170978
+ process.stderr.write(
170979
+ `Token exchange at ${discovery.tokenEndpoint} failed: ${truncateError(
170980
+ err instanceof Error ? err.message : String(err)
170981
+ )}
170982
+ `
170983
+ );
170984
+ return null;
170985
+ });
170986
+ if (!token) return false;
170987
+ emitAccessToken(token.accessToken, discovery, host, json3, reused);
170988
+ return true;
170989
+ };
170990
+ var completeServiceClaim = async (client, discovery, host, claimToken, userCode, json3) => {
170991
+ if (!discovery.claimEndpoint) {
170992
+ process.stderr.write(
170993
+ "The service advertises no claim endpoint \u2014 cannot complete the claim.\n"
170994
+ );
170995
+ return false;
170996
+ }
170997
+ for (let attempt = 0; attempt < CLAIM_NOT_CONFIRMED_RETRIES; attempt++) {
170998
+ const result = await client.auth.identity.completeClaim({
170999
+ claimEndpoint: discovery.claimEndpoint,
171000
+ claimToken,
171001
+ userCode
171002
+ }).catch((err) => {
171003
+ process.stderr.write(
171004
+ `
171005
+ Claim completion failed: ${truncateError(
171006
+ err instanceof Error ? err.message : String(err)
171007
+ )}
171008
+ `
171009
+ );
171010
+ return null;
171011
+ });
171012
+ if (result === null) return false;
171013
+ if (result.status === "not_confirmed") {
171014
+ if (!json3) process.stderr.write(".");
171015
+ await sleep2(CLAIM_NOT_CONFIRMED_INTERVAL_S * 1e3);
171016
+ continue;
171017
+ }
171018
+ if (result.status === "invalid_code") {
171019
+ process.stderr.write(
171020
+ "\nThat pairing code was not accepted. Ask the account owner to re-read the code from the claim page and try again.\n"
171021
+ );
171022
+ return false;
171023
+ }
171024
+ if (result.status === "expired") {
171025
+ process.stderr.write(
171026
+ `
171027
+ The claim attempt is no longer valid (${result.code}). Re-run \`zero auth identity ${host}\` for a fresh one.
171028
+ `
171029
+ );
171030
+ updateServiceIdentity(host, ({ pendingClaim: _drop, ...rest }) => rest);
171031
+ return false;
171032
+ }
171033
+ updateServiceIdentity(host, ({ pendingClaim: _drop, ...rest }) => ({
171034
+ ...rest,
171035
+ assertion: result.identityAssertion,
171036
+ ...result.assertionExpires && {
171037
+ assertionExpires: result.assertionExpires
171038
+ },
171039
+ ...result.refreshToken && { refreshToken: result.refreshToken }
171040
+ }));
171041
+ return exchangeAndEmit(
171042
+ client,
171043
+ discovery,
171044
+ host,
171045
+ result.identityAssertion,
171046
+ json3,
171047
+ false
171048
+ );
171049
+ }
171050
+ process.stderr.write(
171051
+ "\nThe account owner never confirmed the claim on the page. Re-run with --claim-code once they have.\n"
171052
+ );
171053
+ return false;
171054
+ };
171055
+ var authIdentityCommand = (appContext) => new Command("identity").description(
171056
+ "Sign in to a service that accepts ID-JAG identity assertion \u2014 mints one from Zero, registers it, and prints a bearer token for the service's API"
171057
+ ).argument("<url>", "The service host, or any URL on it").option(
171058
+ "--claim-code <code>",
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."
171066
+ ).option("--json", "Emit machine-readable JSON instead of human text").action(
171067
+ async (rawUrl, opts) => {
171068
+ const { client, analyticsService } = appContext.services;
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
+ }
171075
+ const target = normalizeUrl(rawUrl);
171076
+ if (!target) {
171077
+ process.stderr.write(`Not a valid URL or host: ${rawUrl}
171078
+ `);
171079
+ process.exitCode = 1;
171080
+ return;
171081
+ }
171082
+ const host = target.host;
171083
+ const capture = (outcome2) => analyticsService.capture("auth_identity_asserted", {
171084
+ host,
171085
+ outcome: outcome2,
171086
+ json: json3
171087
+ });
171088
+ if (client.getCredentials().kind !== "session") {
171089
+ process.stderr.write(
171090
+ "Identity assertion needs a signed-in Zero session. Run `zero auth login` (humans) or `zero auth agent register` + `zero auth agent claim` (agents) first.\n"
171091
+ );
171092
+ process.exitCode = 1;
171093
+ return;
171094
+ }
171095
+ let discovery;
171096
+ try {
171097
+ discovery = await client.auth.identity.discover(target.toString());
171098
+ } catch (err) {
171099
+ capture("unsupported");
171100
+ process.stderr.write(
171101
+ `${truncateError(err instanceof Error ? err.message : String(err))}
171102
+ This host does not appear to support agent auth. If it serves an /auth.md, follow that instead.
171103
+ `
171104
+ );
171105
+ process.exitCode = 1;
171106
+ return;
171107
+ }
171108
+ if (opts.claimCode) {
171109
+ const pending = readConfig(getConfigPath()).serviceIdentities?.[host]?.pendingClaim;
171110
+ if (!pending) {
171111
+ process.stderr.write(
171112
+ `No pending identity claim for ${host}. Run \`zero auth identity ${host}\` first.
171113
+ `
171114
+ );
171115
+ process.exitCode = 1;
171116
+ return;
171117
+ }
171118
+ const ok = await completeServiceClaim(
171119
+ client,
171120
+ discovery,
171121
+ host,
171122
+ pending.token,
171123
+ opts.claimCode.trim(),
171124
+ json3
171125
+ );
171126
+ capture(ok ? "claim_completed" : "error");
171127
+ if (!ok) process.exitCode = 1;
171128
+ return;
171129
+ }
171130
+ if (!discovery.identityAssertionSupported) {
171131
+ capture("unsupported");
171132
+ process.stderr.write(
171133
+ `${discovery.resourceName ?? host} does not accept identity assertion. Fall back to its standard agent auth (see ${target.origin}/auth.md).
171134
+ `
171135
+ );
171136
+ process.exitCode = 1;
171137
+ return;
171138
+ }
171139
+ const stored = readConfig(getConfigPath()).serviceIdentities?.[host];
171140
+ if (stored?.assertion && isUsable(stored.assertionExpires)) {
171141
+ const token = await client.auth.identity.exchange({
171142
+ tokenEndpoint: discovery.tokenEndpoint,
171143
+ assertion: stored.assertion
171144
+ }).catch(() => null);
171145
+ if (token) {
171146
+ capture("reused");
171147
+ emitAccessToken(token.accessToken, discovery, host, json3, true);
171148
+ return;
171149
+ }
171150
+ }
171151
+ const runAssert = async () => {
171152
+ try {
171153
+ return await client.auth.identity.assert({
171154
+ url: target.toString(),
171155
+ discovery
171156
+ });
171157
+ } catch (err) {
171158
+ capture("error");
171159
+ if (err instanceof ZeroApiError && err.body?.error === "account_unclaimed") {
171160
+ process.stderr.write(
171161
+ "This Zero account has no human owner yet \u2014 identity assertion is only available on claimed accounts. Run `zero auth agent claim <email>` first.\n"
171162
+ );
171163
+ } else {
171164
+ process.stderr.write(
171165
+ `Identity assertion failed: ${truncateError(err instanceof Error ? err.message : String(err))}
171166
+ `
171167
+ );
171168
+ }
171169
+ return null;
171170
+ }
171171
+ };
171172
+ let outcome = await runAssert();
171173
+ if (!outcome) {
171174
+ process.exitCode = 1;
171175
+ return;
171176
+ }
171177
+ if (outcome.status === "consent_required") {
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))}
171187
+ `
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
+ }
171234
+ return;
171235
+ }
171236
+ process.stderr.write(
171237
+ [
171238
+ "",
171239
+ `Signing in to ${discovery.resourceName ?? host} needs the user's one-time consent.`,
171240
+ `Send them here to approve: ${pending.approveUrl}`,
171241
+ `(valid until ${pending.expiresAt}; the decision is remembered on their Zero account)`,
171242
+ "Waiting for their decision\u2026"
171243
+ ].join("\n")
171244
+ );
171245
+ const deadline = opts.finish ? Date.now() + FINISH_CONSENT_WAIT_MS : null;
171246
+ let decision = "pending";
171247
+ for (; ; ) {
171248
+ const status = await client.auth.identity.grantRequest(pending.requestId).catch(() => null);
171249
+ if (status && status.status !== "pending") {
171250
+ decision = status.status;
171251
+ break;
171252
+ }
171253
+ if (deadline !== null && Date.now() >= deadline) break;
171254
+ process.stderr.write(".");
171255
+ await sleep2(CONSENT_POLL_INTERVAL_S * 1e3);
171256
+ }
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
+ );
171282
+ if (decision === "denied") {
171283
+ capture("consent_denied");
171284
+ process.stderr.write(
171285
+ "The user denied the request \u2014 not signing in.\n"
171286
+ );
171287
+ process.exitCode = 1;
171288
+ return;
171289
+ }
171290
+ if (decision === "expired") {
171291
+ capture("consent_expired");
171292
+ process.stderr.write(
171293
+ "The approval link expired before the user decided. Re-run to mint a fresh one.\n"
171294
+ );
171295
+ process.exitCode = 1;
171296
+ return;
171297
+ }
171298
+ outcome = await runAssert();
171299
+ if (!outcome) {
171300
+ process.exitCode = 1;
171301
+ return;
171302
+ }
171303
+ if (outcome.status === "consent_required") {
171304
+ capture("error");
171305
+ process.stderr.write(
171306
+ "The issuer still reports consent_required after approval \u2014 retry, and report this if it persists.\n"
171307
+ );
171308
+ process.exitCode = 1;
171309
+ return;
171310
+ }
171311
+ }
171312
+ switch (outcome.status) {
171313
+ case "ok": {
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
+ );
171335
+ const ok = await exchangeAndEmit(
171336
+ client,
171337
+ discovery,
171338
+ host,
171339
+ outcome.registration.identityAssertion,
171340
+ json3,
171341
+ false
171342
+ );
171343
+ capture(ok ? "ok" : "error");
171344
+ if (!ok) process.exitCode = 1;
171345
+ return;
171346
+ }
171347
+ case "unsupported":
171348
+ case "issuer_not_enabled": {
171349
+ capture(outcome.status);
171350
+ process.stderr.write(
171351
+ `${discovery.resourceName ?? host} does not accept Zero identity assertions${outcome.status === "issuer_not_enabled" ? " (Zero is not on its issuer trust list)" : ""}. Fall back to its standard agent auth (see ${target.origin}/auth.md).
171352
+ `
171353
+ );
171354
+ process.exitCode = 1;
171355
+ return;
171356
+ }
171357
+ case "login_required": {
171358
+ capture("login_required");
171359
+ process.stderr.write(
171360
+ `The service requires a fresher Zero sign-in${outcome.description ? ` (${outcome.description})` : ""}. Run \`zero auth login\` again, then retry \u2014 nothing at the service side helps.
171361
+ `
171362
+ );
171363
+ process.exitCode = 1;
171364
+ return;
171365
+ }
171366
+ case "interaction_required": {
171367
+ capture("interaction_required");
171368
+ const { claim: claim3 } = outcome;
171369
+ if (!claim3.claimToken || !claim3.verificationUri) {
171370
+ process.stderr.write(
171371
+ `The service requires account-owner confirmation but returned no claim handle${claim3.description ? ` (${claim3.description})` : ""}.
171372
+ `
171373
+ );
171374
+ process.exitCode = 1;
171375
+ return;
171376
+ }
171377
+ updateServiceIdentity(host, (current) => ({
171378
+ ...current,
171379
+ pendingClaim: {
171380
+ token: claim3.claimToken,
171381
+ verificationUri: claim3.verificationUri ?? void 0,
171382
+ expiresAt: claim3.claimTokenExpires ?? void 0
171383
+ }
171384
+ }));
171385
+ if (json3) {
171386
+ process.stdout.write(
171387
+ `${JSON.stringify({
171388
+ status: "interaction_required",
171389
+ verificationUri: claim3.verificationUri,
171390
+ expiresAt: claim3.claimTokenExpires,
171391
+ next: `The claim page shows the account owner a pairing code. Re-run \`zero auth identity ${host} --claim-code <code>\` with it.`
171392
+ })}
171393
+ `
171394
+ );
171395
+ } else {
171396
+ process.stderr.write(
171397
+ [
171398
+ "",
171399
+ `Your email already has an account at ${discovery.resourceName ?? host} \u2014 its owner must confirm the link.`,
171400
+ `Send them here: ${claim3.verificationUri}`,
171401
+ "The page shows THEM a pairing code.",
171402
+ ...claim3.claimTokenExpires ? [`(link valid until ${claim3.claimTokenExpires})`] : [],
171403
+ ""
171404
+ ].join("\n")
171405
+ );
171406
+ }
171407
+ if (!process.stdin.isTTY) {
171408
+ if (!json3) {
171409
+ process.stderr.write(
171410
+ `Once they read the code back, run: zero auth identity ${host} --claim-code <code>
171411
+ `
171412
+ );
171413
+ }
171414
+ return;
171415
+ }
171416
+ const rl = createInterface$1({
171417
+ input: process.stdin,
171418
+ output: process.stderr
171419
+ });
171420
+ const userCode = (await rl.question("Enter the pairing code they read back: ")).trim();
171421
+ rl.close();
171422
+ if (!userCode) {
171423
+ process.stderr.write(
171424
+ `No code entered. Re-run \`zero auth identity ${host} --claim-code <code>\` when you have it.
171425
+ `
171426
+ );
171427
+ process.exitCode = 1;
171428
+ return;
171429
+ }
171430
+ const ok = await completeServiceClaim(
171431
+ client,
171432
+ discovery,
171433
+ host,
171434
+ claim3.claimToken,
171435
+ userCode,
171436
+ json3
171437
+ );
171438
+ if (!ok) process.exitCode = 1;
171439
+ return;
171440
+ }
171441
+ }
171442
+ }
171443
+ );
171444
+
171445
+ // src/commands/auth-command.ts
171446
+ var getConfigPath2 = () => join$1(homedir(), ".zero", "config.json");
170613
171447
  var FINISH_POLL_INTERVAL_S = 2;
170614
171448
  var FINISH_MAX_WAIT_MS = 10 * 60 * 1e3;
170615
- var sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
171449
+ var sleep3 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
170616
171450
  var persistSession = (result) => {
170617
- const path3 = getConfigPath();
171451
+ const path3 = getConfigPath2();
170618
171452
  ensureSecureDir(dirname(path3));
170619
171453
  const current = readConfig(path3);
170620
171454
  const next = {
@@ -170632,7 +171466,7 @@ var LEGACY_KEY_NOTICE = {
170632
171466
  message: "A wallet private key from a previous setup is still on this machine. Now that you're signed in, your managed Zero wallet signs payments \u2014 the old key is no longer used.",
170633
171467
  keep: "zero wallet set <key>"
170634
171468
  };
170635
- var hasLegacyPrivateKey = () => readConfig(getConfigPath()).privateKey !== void 0;
171469
+ var hasLegacyPrivateKey = () => readConfig(getConfigPath2()).privateKey !== void 0;
170636
171470
  var reportSignedIn = (result, json3, la) => {
170637
171471
  const legacyKeyPresent = hasLegacyPrivateKey();
170638
171472
  la?.analytics.capture("auth_login_completed", {
@@ -170732,7 +171566,7 @@ var runFinish = async (client, deviceCode, json3, la) => {
170732
171566
  } else if (!json3) {
170733
171567
  process.stdout.write(".");
170734
171568
  }
170735
- await sleep2(FINISH_POLL_INTERVAL_S * 1e3);
171569
+ await sleep3(FINISH_POLL_INTERVAL_S * 1e3);
170736
171570
  continue;
170737
171571
  }
170738
171572
  if (result.status === "expired") {
@@ -170759,7 +171593,7 @@ User code: ${start.userCode}
170759
171593
  });
170760
171594
  }
170761
171595
  while (Date.now() < start.expiresAt) {
170762
- await sleep2(start.pollInterval * 1e3);
171596
+ await sleep3(start.pollInterval * 1e3);
170763
171597
  const result = await client.auth.device.poll(start.deviceCode);
170764
171598
  if (result.status === "pending") {
170765
171599
  process.stdout.write(".");
@@ -170795,7 +171629,7 @@ var authLoginCommand = (appContext) => new Command("login").description("Sign in
170795
171629
  return;
170796
171630
  }
170797
171631
  const mode = opts.finish ? "finish" : "interactive";
170798
- const hadPriorSession = readConfig(getConfigPath()).session !== void 0;
171632
+ const hadPriorSession = readConfig(getConfigPath2()).session !== void 0;
170799
171633
  analyticsService.capture("auth_login_started", { mode, json: json3 });
170800
171634
  const la = {
170801
171635
  analytics: analyticsService,
@@ -170820,7 +171654,7 @@ var authLoginCommand = (appContext) => new Command("login").description("Sign in
170820
171654
  );
170821
171655
  var authLogoutCommand = (appContext) => new Command("logout").description("Sign out of Zero").action(async () => {
170822
171656
  const { client, analyticsService } = appContext.services;
170823
- const path3 = getConfigPath();
171657
+ const path3 = getConfigPath2();
170824
171658
  const config3 = readConfig(path3);
170825
171659
  const hadSession = config3.session !== void 0;
170826
171660
  if (config3.session) {
@@ -170925,7 +171759,7 @@ var authAgentRegisterCommand = (appContext) => new Command("register").descripti
170925
171759
  ).option("--json", "Emit machine-readable JSON instead of human text").action(async (opts) => {
170926
171760
  const { client } = appContext.services;
170927
171761
  const json3 = opts.json ?? false;
170928
- const path3 = getConfigPath();
171762
+ const path3 = getConfigPath2();
170929
171763
  if (readConfig(path3).session) {
170930
171764
  process.stderr.write(
170931
171765
  "Already signed in. Run `zero auth logout` first if you want a fresh account.\n"
@@ -171005,12 +171839,12 @@ Agent registration may not be enabled for this service yet.
171005
171839
  ].join("\n")
171006
171840
  );
171007
171841
  });
171008
- var CLAIM_NOT_CONFIRMED_RETRIES = 12;
171009
- var CLAIM_NOT_CONFIRMED_INTERVAL_S = 5;
171842
+ var CLAIM_NOT_CONFIRMED_RETRIES2 = 12;
171843
+ var CLAIM_NOT_CONFIRMED_INTERVAL_S2 = 5;
171010
171844
  var completeClaimAndExchange = async (agentAuth, claimToken, userCode, email5, json3) => {
171011
- const path3 = getConfigPath();
171845
+ const path3 = getConfigPath2();
171012
171846
  let verified = null;
171013
- for (let attempt = 0; attempt < CLAIM_NOT_CONFIRMED_RETRIES; attempt++) {
171847
+ for (let attempt = 0; attempt < CLAIM_NOT_CONFIRMED_RETRIES2; attempt++) {
171014
171848
  const result = await agentAuth.completeClaim({ claimToken, userCode }).catch((err) => {
171015
171849
  process.stderr.write(
171016
171850
  `
@@ -171022,7 +171856,7 @@ Claim completion failed: ${truncateError(err instanceof Error ? err.message : St
171022
171856
  if (result === null) return false;
171023
171857
  if (result.status === "not_confirmed") {
171024
171858
  if (!json3) process.stdout.write(".");
171025
- await sleep2(CLAIM_NOT_CONFIRMED_INTERVAL_S * 1e3);
171859
+ await sleep3(CLAIM_NOT_CONFIRMED_INTERVAL_S2 * 1e3);
171026
171860
  continue;
171027
171861
  }
171028
171862
  if (result.status === "invalid_code") {
@@ -171090,7 +171924,7 @@ var authAgentClaimCommand = (appContext) => new Command("claim").description(
171090
171924
  ).option("--json", "Emit machine-readable JSON instead of human text").action(async (email5, opts) => {
171091
171925
  const { client } = appContext.services;
171092
171926
  const json3 = opts.json ?? false;
171093
- const config3 = readConfig(getConfigPath());
171927
+ const config3 = readConfig(getConfigPath2());
171094
171928
  const registration = config3.agentRegistration;
171095
171929
  if (!registration?.claimToken) {
171096
171930
  process.stderr.write(
@@ -171183,13 +172017,13 @@ var authAgentCommand = (appContext) => {
171183
172017
  return cmd;
171184
172018
  };
171185
172019
  var ensureAuthenticated = async (client, shouldOpen = true) => {
171186
- const session5 = readConfig(getConfigPath()).session;
172020
+ const session5 = readConfig(getConfigPath2()).session;
171187
172021
  if (session5) return;
171188
172022
  process.stdout.write(
171189
172023
  "\nZero requires authentication before handing off to Claude.\n\n"
171190
172024
  );
171191
172025
  await runInteractive(client, shouldOpen);
171192
- if (!readConfig(getConfigPath()).session) {
172026
+ if (!readConfig(getConfigPath2()).session) {
171193
172027
  process.exitCode = 1;
171194
172028
  process.exit(1);
171195
172029
  }
@@ -171198,6 +172032,7 @@ var authCommand = (appContext) => {
171198
172032
  const cmd = new Command("auth").description("Authentication commands");
171199
172033
  cmd.addCommand(authLoginCommand(appContext).alias("register"));
171200
172034
  cmd.addCommand(authAgentCommand(appContext));
172035
+ cmd.addCommand(authIdentityCommand(appContext));
171201
172036
  cmd.addCommand(authLogoutCommand(appContext));
171202
172037
  cmd.addCommand(authExchangeCommand(appContext));
171203
172038
  cmd.addCommand(authWhoamiCommand(appContext), { hidden: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.28.0",
3
+ "version": "1.29.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",