@gatemux/dsh-gatemux-login 1.0.1 → 1.0.2

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/account.js +22 -7
  2. package/package.json +1 -1
package/account.js CHANGED
@@ -68,6 +68,16 @@ function parseGrant(payload, issuer) {
68
68
  return { version: 1, accessToken, refreshToken, expiresAt, issuer }
69
69
  }
70
70
 
71
+ /**
72
+ * Read a stored record as a grant this deployment may use.
73
+ * @param record - record at this provider's key, or undefined when none is stored.
74
+ * @param issuer - origin a grant must carry to be usable here.
75
+ * @returns the parsed grant, or null when no record is stored or it is unusable.
76
+ */
77
+ function usableGrant(record, issuer) {
78
+ return record !== undefined && record.kind === 'grant' ? parseGrant(record.payload, issuer) : null
79
+ }
80
+
71
81
  /** Accept a bare HTTPS origin, rejecting paths, credentials, and non-HTTPS schemes. */
72
82
  function originOf(value) {
73
83
  let url
@@ -182,22 +192,27 @@ export class GateMuxAccount extends DeepSeekAccount {
182
192
  /** Discard a stored grant issued by another environment. */
183
193
  async [Service.init]() {
184
194
  const record = await this.ctx.credentials.readRecord(KEY)
185
- if (record === undefined) return
186
- const grant = record.kind === 'grant' ? parseGrant(record.payload, this.issuer) : null
187
- if (grant !== null) return
195
+ if (record === undefined || usableGrant(record, this.issuer) !== null) return
188
196
  await this.ctx.credentials.deleteRecord(KEY)
189
197
  this.logger.warn('stored grant discarded', { reason: 'unreadable-or-foreign-issuer' })
190
198
  }
191
199
 
192
200
  async getState() {
193
201
  const record = await this.ctx.credentials.readRecord(KEY)
194
- if (record !== undefined && (record.kind !== 'grant' || parseGrant(record.payload, this.issuer) === null)) {
195
- throw new GateMuxAuthError('stored grant is unreadable', 'storage')
202
+ const grant = usableGrant(record, this.issuer)
203
+ // A record this deployment cannot use reads as absent instead of raising: every
204
+ // caller turns a throw into a failure with no diagnosis. `startSignIn` returns
205
+ // this outside its own catch, so a raise there rejects the start call and the
206
+ // dialog reports a sign-in failure for a record the person never supplied, and
207
+ // `watch` ends the account stream. The record is left in place for a sign-in to
208
+ // overwrite; discarding it here could delete a grant committed since the read.
209
+ if (record !== undefined && grant === null) {
210
+ this.logger.warn('stored grant is unreadable', { reason: 'unreadable-or-foreign-issuer' })
196
211
  }
197
212
  const attempt = this.attempt?.view ?? null
198
213
  return {
199
- status: record === undefined ? 'signed-out' : 'credential-stored',
200
- attempt: record === undefined && attempt?.phase === 'succeeded' ? null : attempt,
214
+ status: grant === null ? 'signed-out' : 'credential-stored',
215
+ attempt: grant === null && attempt?.phase === 'succeeded' ? null : attempt,
201
216
  links: {
202
217
  usageUrl: `${this.consoleOrigin}/app/usage`,
203
218
  topUpUrl: `${this.consoleOrigin}/app/billing`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gatemux/dsh-gatemux-login",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "Sign in with GateMux for DeepSeek Harness: users pay from their own GateMux balance.",
6
6
  "publishConfig": {