@enbox/auth 0.6.32 → 0.6.33

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 (36) hide show
  1. package/dist/esm/auth-manager.js +78 -43
  2. package/dist/esm/auth-manager.js.map +1 -1
  3. package/dist/esm/connect/lifecycle.js +29 -31
  4. package/dist/esm/connect/lifecycle.js.map +1 -1
  5. package/dist/esm/connect/restore.js +3 -2
  6. package/dist/esm/connect/restore.js.map +1 -1
  7. package/dist/esm/connect/wallet.js +10 -2
  8. package/dist/esm/connect/wallet.js.map +1 -1
  9. package/dist/esm/identity-session.js +11 -23
  10. package/dist/esm/identity-session.js.map +1 -1
  11. package/dist/esm/password-provider.js.map +1 -1
  12. package/dist/esm/types.js.map +1 -1
  13. package/dist/esm/wallet-connect-client.js +12 -10
  14. package/dist/esm/wallet-connect-client.js.map +1 -1
  15. package/dist/types/auth-manager.d.ts +36 -12
  16. package/dist/types/auth-manager.d.ts.map +1 -1
  17. package/dist/types/connect/lifecycle.d.ts +16 -2
  18. package/dist/types/connect/lifecycle.d.ts.map +1 -1
  19. package/dist/types/connect/restore.d.ts.map +1 -1
  20. package/dist/types/connect/wallet.d.ts.map +1 -1
  21. package/dist/types/identity-session.d.ts +11 -42
  22. package/dist/types/identity-session.d.ts.map +1 -1
  23. package/dist/types/password-provider.d.ts +25 -9
  24. package/dist/types/password-provider.d.ts.map +1 -1
  25. package/dist/types/types.d.ts +18 -13
  26. package/dist/types/types.d.ts.map +1 -1
  27. package/dist/types/wallet-connect-client.d.ts.map +1 -1
  28. package/package.json +11 -7
  29. package/src/auth-manager.ts +98 -57
  30. package/src/connect/lifecycle.ts +58 -36
  31. package/src/connect/restore.ts +15 -5
  32. package/src/connect/wallet.ts +11 -3
  33. package/src/identity-session.ts +11 -55
  34. package/src/password-provider.ts +27 -11
  35. package/src/types.ts +19 -15
  36. package/src/wallet-connect-client.ts +13 -11
@@ -12,7 +12,8 @@ import type { RestoreSessionOptions } from '../types.js';
12
12
 
13
13
  import type { StorageAdapter } from '../types.js';
14
14
 
15
- import type { EnboxUserAgent } from '@enbox/agent';
15
+ import type { RecordsWriteMessage } from '@enbox/dwn-sdk-js';
16
+ import type { DwnDataEncodedRecordsWriteMessage, EnboxUserAgent } from '@enbox/agent';
16
17
 
17
18
  import { Convert } from '@enbox/common';
18
19
  import { DataStream } from '@enbox/dwn-sdk-js';
@@ -392,7 +393,16 @@ async function ensureRevocationGrantOnRemote(
392
393
  });
393
394
  if (reply.status.code !== 200 || !reply.entry?.recordsWrite) { return; }
394
395
 
395
- const { encodedData, ...rawMessage } = reply.entry.recordsWrite as any;
396
+ // `RecordsWriteMessage` doesn't declare `encodedData`, but the
397
+ // wire-format reply may include it; widen the local type to
398
+ // acknowledge that without `any`.
399
+ // NOSONAR S4325 false positive: the cast is required to typecheck
400
+ // the destructuring of the undeclared optional `encodedData`
401
+ // property; removing it fails TS2339. Sonar reads the intersection-
402
+ // with-optional-field as a no-op widening, which it isn't here.
403
+ type RecordsWriteWireMessage = RecordsWriteMessage & { encodedData?: string };
404
+ const { encodedData: _encoded, ...rawMessage } =
405
+ reply.entry.recordsWrite as RecordsWriteWireMessage; // NOSONAR
396
406
  const data = reply.entry.data
397
407
  ? new Blob([await DataStream.toBytes(reply.entry.data) as BlobPart])
398
408
  : undefined;
@@ -439,18 +449,18 @@ async function revokeAndSendSingle(
439
449
  messageType : DwnInterface.RecordsRead,
440
450
  messageParams : { filter: { recordId: entry.grantId } },
441
451
  });
442
- if (readReply.status.code !== 200 || !readReply.entry) { return false; }
452
+ if (readReply.status.code !== 200 || !readReply.entry?.recordsWrite) { return false; }
443
453
 
444
454
  // Reconstruct DwnDataEncodedRecordsWriteMessage: RecordsRead returns
445
455
  // the data as a stream, but PermissionGrant.parse needs encodedData.
446
456
  const grantDataBytes = readReply.entry.data
447
457
  ? await DataStream.toBytes(readReply.entry.data)
448
458
  : new Uint8Array(0);
449
- const grantMessageWithData = {
459
+ const grantMessageWithData: DwnDataEncodedRecordsWriteMessage = {
450
460
  ...readReply.entry.recordsWrite,
451
461
  encodedData: Convert.uint8Array(grantDataBytes).toBase64Url(),
452
462
  };
453
- const grant = DwnPermissionGrant.parse(grantMessageWithData as any);
463
+ const grant = DwnPermissionGrant.parse(grantMessageWithData);
454
464
 
455
465
  const { message } = await userAgent.permissions.createRevocation({
456
466
  author : connectedDid,
@@ -60,7 +60,6 @@ export async function walletConnect(
60
60
  const identity = await importDelegateAndSetupSync({
61
61
  userAgent, delegatePortableDid, connectedDid, delegateGrants,
62
62
  delegateDecryptionKeys, delegateContextKeys, delegateMultiPartyProtocols,
63
- sessionRevocations,
64
63
  flowName: 'Wallet connect',
65
64
  });
66
65
 
@@ -80,9 +79,18 @@ export async function walletConnect(
80
79
  );
81
80
  }
82
81
 
83
- // Finalize session.
82
+ // Finalize session. Pass the transient delegate state explicitly so
83
+ // `persistOrClearDelegateSecrets` doesn't have to read it back off
84
+ // the identity object (which was the old `(identity as any)._foo`
85
+ // smuggling pattern).
84
86
  return finalizeDelegateSession({
85
87
  userAgent, emitter, storage, identity,
86
- connectedDid, delegateDid: delegatePortableDid.uri, sync,
88
+ connectedDid, delegateDid : delegatePortableDid.uri, sync,
89
+ delegateState : {
90
+ delegateDecryptionKeys,
91
+ delegateContextKeys,
92
+ delegateMultiPartyProtocols,
93
+ sessionRevocations,
94
+ },
87
95
  });
88
96
  }
@@ -1,65 +1,21 @@
1
1
  /**
2
- * AuthSession represents an active, authenticated session with a specific identity.
3
- * @module
4
- */
5
-
6
- import type { EnboxAgent } from '@enbox/agent';
7
-
8
- import type { IdentityInfo } from './types.js';
9
-
10
- /**
11
- * An active, authenticated session bound to a specific identity.
2
+ * `AuthSession` is an alias for {@link AgentSession} from `@enbox/agent`.
12
3
  *
13
- * The session exposes the authenticated **agent**, **did**, and
14
- * **delegateDid** the primitives needed to interact with the DWN
15
- * network. Consumers that use `@enbox/api` can construct an `Enbox`
16
- * instance from these properties:
4
+ * The alias exists so `@enbox/auth`'s public surface stays self-contained.
5
+ * `new AuthSession(...)` constructs an `AgentSession`, and `instanceof
6
+ * AuthSession` and `instanceof AgentSession` both succeed on any session
7
+ * created through either name. New code should prefer `AgentSession`
8
+ * directly.
17
9
  *
10
+ * @example
18
11
  * ```ts
19
12
  * import { Enbox } from '@enbox/api';
20
13
  *
21
14
  * const session = await auth.connect();
22
- * const enbox = Enbox.connect({
23
- * agent: session.agent,
24
- * connectedDid: session.did,
25
- * delegateDid: session.delegateDid,
26
- * });
15
+ * const enbox = Enbox.fromSession(session);
27
16
  * ```
17
+ *
18
+ * @module
28
19
  */
29
- export class AuthSession {
30
- /** The authenticated Enbox agent managing keys, DIDs, and DWN access. */
31
- readonly agent: EnboxAgent;
32
-
33
- /** The DID URI of the connected identity. */
34
- readonly did: string;
35
-
36
- /**
37
- * The delegate DID URI, present when connected via wallet connect.
38
- * This is the locally-created DID that holds delegated permissions
39
- * from the wallet's identity.
40
- */
41
- readonly delegateDid?: string;
42
-
43
- /**
44
- * The BIP-39 recovery phrase, present only on first-time local connect.
45
- * Should be shown to the user for backup and then discarded from memory.
46
- */
47
- readonly recoveryPhrase?: string;
48
-
49
- /** Metadata about the connected identity. */
50
- readonly identity: IdentityInfo;
51
20
 
52
- constructor(params: {
53
- agent: EnboxAgent;
54
- did: string;
55
- delegateDid?: string;
56
- recoveryPhrase?: string;
57
- identity: IdentityInfo;
58
- }) {
59
- this.agent = params.agent;
60
- this.did = params.did;
61
- this.delegateDid = params.delegateDid;
62
- this.recoveryPhrase = params.recoveryPhrase;
63
- this.identity = params.identity;
64
- }
65
- }
21
+ export { AgentSession as AuthSession } from '@enbox/agent';
@@ -56,15 +56,25 @@ export interface PasswordProvider {
56
56
 
57
57
  // ─── Internal I/O interfaces (for testing) ───────────────────────
58
58
 
59
- /** @internal Minimal interface for an stdin-like readable stream. */
59
+ /**
60
+ * Minimal interface for an stdin-like readable stream.
61
+ *
62
+ * The signature shape mirrors Node's `tty.ReadStream` closely enough
63
+ * that `process.stdin` is directly assignable without a cast — the
64
+ * payoff is that `readPasswordRawMode` is testable with a tiny in-memory
65
+ * stub and the production call site needs no `as` to bridge to Node's
66
+ * actual stdin type.
67
+ *
68
+ * @internal
69
+ */
60
70
  export interface TtyReadable {
61
71
  isTTY?: boolean;
62
- setRawMode(mode: boolean): void;
63
- setEncoding(encoding: string): void;
64
- resume(): void;
65
- pause(): void;
66
- on(event: 'data', listener: (chunk: string) => void): void;
67
- removeListener(event: 'data', listener: (chunk: string) => void): void;
72
+ setRawMode(mode: boolean): unknown;
73
+ setEncoding(encoding?: BufferEncoding): unknown;
74
+ resume(): unknown;
75
+ pause(): unknown;
76
+ on(event: 'data', listener: (chunk: string) => void): unknown;
77
+ removeListener(event: 'data', listener: (chunk: string) => void): unknown;
68
78
  }
69
79
 
70
80
  /** @internal Minimal interface for an stdout-like writable stream. */
@@ -127,13 +137,19 @@ export function readPasswordRawMode(
127
137
  });
128
138
  }
129
139
 
130
- /** @internal Injectable I/O for testing `readPasswordDevTty`. */
140
+ /**
141
+ * @internal Injectable I/O for testing `readPasswordDevTty`.
142
+ *
143
+ * `execSync`'s `stdio` is narrowed to the literal-union Node accepts so
144
+ * the implementation below can call `child_process.execSync` without a
145
+ * `stdio: string -> stdio: StdioOptions` cast.
146
+ */
131
147
  export interface DevTtyIo {
132
148
  openSync(path: string, flags: string): number;
133
149
  readSync(fd: number, buf: Uint8Array, offset: number, length: number, position: null): number;
134
150
  writeSync(fd: number, data: string): number;
135
151
  closeSync(fd: number): void;
136
- execSync(cmd: string, opts: { stdio: string }): void;
152
+ execSync(cmd: string, opts: { stdio: 'pipe' | 'ignore' | 'inherit' }): void;
137
153
  }
138
154
 
139
155
  /**
@@ -162,7 +178,7 @@ export async function readPasswordDevTty(
162
178
  readSync,
163
179
  writeSync,
164
180
  closeSync,
165
- execSync: (cmd: string, opts: { stdio: string }): void => { execSync(cmd, opts as any); },
181
+ execSync: (cmd: string, opts: { stdio: 'pipe' | 'ignore' | 'inherit' }): void => { execSync(cmd, opts); },
166
182
  };
167
183
  }
168
184
 
@@ -303,7 +319,7 @@ export namespace PasswordProvider {
303
319
  }
304
320
 
305
321
  return readPasswordRawMode(
306
- process.stdin as unknown as TtyReadable,
322
+ process.stdin,
307
323
  process.stdout,
308
324
  prompt,
309
325
  );
package/src/types.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { PortableDid } from '@enbox/dids';
7
- import type { ConnectPermissionRequest, DelegateContextKey, DelegateDecryptionKey, DwnDataEncodedRecordsWriteMessage, DwnProtocolDefinition, EnboxUserAgent, HdIdentityVault, LocalDwnStrategy, PortableIdentity } from '@enbox/agent';
7
+ import type { AgentSessionIdentity, ConnectPermissionRequest, DelegateContextKey, DelegateDecryptionKey, DwnDataEncodedRecordsWriteMessage, DwnProtocolDefinition, EnboxUserAgent, HdIdentityVault, LocalDwnStrategy, PortableIdentity } from '@enbox/agent';
8
8
 
9
9
  import type { PasswordProvider } from './password-provider.js';
10
10
 
@@ -79,20 +79,15 @@ export type AuthEventHandler<E extends AuthEvent = AuthEvent> =
79
79
 
80
80
  // ─── Identity ────────────────────────────────────────────────────
81
81
 
82
- /** Lightweight metadata about a stored identity. */
83
- export interface IdentityInfo {
84
- /** The DID URI for this identity. */
85
- didUri: string;
86
-
87
- /** Human-readable name. */
88
- name: string;
89
-
90
- /**
91
- * Present when this identity is a delegate of another DID
92
- * (i.e. connected via wallet connect).
93
- */
94
- connectedDid?: string;
95
- }
82
+ /**
83
+ * Lightweight metadata about a stored identity.
84
+ *
85
+ * @deprecated Prefer {@link AgentSessionIdentity} from `@enbox/agent` — this
86
+ * alias exists for `@enbox/auth`'s self-contained public surface but the
87
+ * canonical name lives in the agent package. The two are structurally
88
+ * identical; new code should import `AgentSessionIdentity` directly.
89
+ */
90
+ export type IdentityInfo = AgentSessionIdentity;
96
91
 
97
92
  /** Serializable session info for the `session-start` event. */
98
93
  export interface AuthSessionInfo {
@@ -492,6 +487,15 @@ export interface HandlerConnectOptions {
492
487
  */
493
488
  connectHandler?: ConnectHandler;
494
489
 
490
+ /**
491
+ * Vault password for this call (overrides the manager default).
492
+ *
493
+ * The handler flow still needs to unlock the local agent's vault to receive
494
+ * delegated grants — passing `password` per-call lets callers override the
495
+ * default supplied to `AuthManager.create()`.
496
+ */
497
+ password?: string;
498
+
495
499
  /** Override manager default sync interval. */
496
500
  sync?: SyncOption;
497
501
  }
@@ -126,7 +126,7 @@ async function initClient({
126
126
  // Sign the request as a JWT.
127
127
  const requestJwt = await EnboxConnectProtocol.signJwt({
128
128
  did : clientDid,
129
- data : request as unknown as Record<string, unknown>,
129
+ data : request,
130
130
  });
131
131
 
132
132
  if (!requestJwt) {
@@ -191,18 +191,20 @@ async function initClient({
191
191
  // Get the PIN from the user and use it as AAD to decrypt.
192
192
  const pin = await validatePin();
193
193
  const jwt = await EnboxConnectProtocol.decryptResponse(clientDid, jwe, pin);
194
- const verifiedResponse = (await EnboxConnectProtocol.verifyJwt({
195
- jwt,
196
- })) as unknown as EnboxConnectResponse;
194
+ const verifiedPayload = await EnboxConnectProtocol.verifyJwt({ jwt });
195
+ // Runtime narrowing — see `assertConnectResponse` in @enbox/agent for
196
+ // the shape validated. After this line `verifiedPayload` is narrowed
197
+ // to `EnboxConnectResponse`.
198
+ EnboxConnectProtocol.assertConnectResponse(verifiedPayload);
197
199
 
198
200
  return {
199
- delegateGrants : verifiedResponse.delegateGrants,
200
- delegatePortableDid : verifiedResponse.delegatePortableDid,
201
- connectedDid : verifiedResponse.providerDid,
202
- delegateDecryptionKeys : verifiedResponse.delegateDecryptionKeys,
203
- delegateContextKeys : verifiedResponse.delegateContextKeys,
204
- delegateMultiPartyProtocols : verifiedResponse.delegateMultiPartyProtocols,
205
- sessionRevocations : verifiedResponse.sessionRevocations,
201
+ delegateGrants : verifiedPayload.delegateGrants,
202
+ delegatePortableDid : verifiedPayload.delegatePortableDid,
203
+ connectedDid : verifiedPayload.providerDid,
204
+ delegateDecryptionKeys : verifiedPayload.delegateDecryptionKeys,
205
+ delegateContextKeys : verifiedPayload.delegateContextKeys,
206
+ delegateMultiPartyProtocols : verifiedPayload.delegateMultiPartyProtocols,
207
+ sessionRevocations : verifiedPayload.sessionRevocations,
206
208
  };
207
209
  }
208
210
  }