signify-ts 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -154,6 +154,20 @@ Account Creation Workflow
154
154
 
155
155
  This package is published on npm: https://www.npmjs.com/package/signify-ts.
156
156
 
157
+ ## Release publishing
158
+
159
+ Releases are published with npm trusted publishing from GitHub Actions. The
160
+ normal release flow is:
161
+
162
+ 1. Validate the release locally.
163
+ 2. Create and push a signed version tag.
164
+ 3. Run the `Publish NPM` workflow against that tag with the intended npm dist tag.
165
+ 4. Approve the `npm-publish` GitHub environment when prompted.
166
+ 5. Verify the published package and npm dist tag.
167
+
168
+ The npm package has a trusted publisher configured for the `WebOfTrust/signify-ts` repository,
169
+ the `publish-npm.yml` workflow, and the `npm-publish` environment.
170
+
157
171
  If you need to publish a version under your own scope, you can use the [publish script](./publish.sh). This enables you to create development packages. For example:
158
172
 
159
173
  ```bash
@@ -189,3 +203,7 @@ npm notice
189
203
  npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access (dry-run)
190
204
  + @myorg/signify-ts@0.3.0-rc1
191
205
  ```
206
+
207
+ Direct local publishing to the public `signify-ts` package should be treated as
208
+ an emergency fallback. It requires an npm account with publish access and any
209
+ OTP required by npm.
package/dist/exports.d.ts CHANGED
@@ -38,3 +38,4 @@ export * from './keri/core/utils.ts';
38
38
  export * from './keri/core/verfer.ts';
39
39
  export * from './keri/core/keyState.ts';
40
40
  export * from './keri/end/ending.ts';
41
+ export * as KeriaApi from './types/keria-api-schema.ts';
package/dist/exports.js CHANGED
@@ -38,3 +38,4 @@ export * from "./keri/core/utils.js";
38
38
  export * from "./keri/core/verfer.js";
39
39
  export * from "./keri/core/keyState.js";
40
40
  export * from "./keri/end/ending.js";
41
+ export * as KeriaApi from "./types/keria-api-schema.js";
@@ -2,7 +2,7 @@ import { Tier } from '../core/salter.ts';
2
2
  import { Algos } from '../core/manager.ts';
3
3
  import { Serder } from '../core/serder.ts';
4
4
  import { IdentifierManagerFactory } from '../core/keeping.ts';
5
- import { HabState } from '../core/keyState.ts';
5
+ import { HabState, PendingHabState } from '../core/keyState.ts';
6
6
  import { components } from '../../types/keria-api-schema.ts';
7
7
  /** Arguments required to create an identfier */
8
8
  export interface CreateIdentiferArgs {
@@ -86,17 +86,32 @@ export declare class Identifier {
86
86
  * Get information for a managed identifier
87
87
  * @async
88
88
  * @param {string} name Prefix or alias of the identifier
89
- * @returns {Promise<HabState>} A promise to the identifier information
89
+ * @param {boolean} [requireAccepted=true] When true, requires key state to
90
+ * be present and throws otherwise. Key state is absent only for a
91
+ * multisig group whose inception is still collecting member
92
+ * signatures; pass false to fetch such a pending group.
93
+ * @returns {Promise<HabState | PendingHabState>} A promise to the
94
+ * identifier information, narrowed to HabState unless requireAccepted
95
+ * is false
90
96
  */
91
- get(name: string): Promise<HabState>;
97
+ get(name: string, requireAccepted?: true): Promise<HabState>;
98
+ get(name: string, requireAccepted: false): Promise<HabState | PendingHabState>;
99
+ get(name: string, requireAccepted: boolean): Promise<HabState | PendingHabState>;
92
100
  /**
93
101
  * Update managed identifier
94
102
  * @async
95
103
  * @param {string} name Prefix or alias of the identifier
96
104
  * @param {IdentifierInfo} info Information to update for the given identifier
97
- * @returns {Promise<HabState>} A promise to the identifier information after updating
105
+ * @param {boolean} [requireAccepted=true] When true, requires key state to
106
+ * be present on the updated identifier and throws otherwise; pass
107
+ * false to update a still-pending multisig group.
108
+ * @returns {Promise<HabState | PendingHabState>} A promise to the
109
+ * identifier information after updating, narrowed to HabState unless
110
+ * requireAccepted is false
98
111
  */
99
- update(name: string, info: IdentifierInfo): Promise<HabState>;
112
+ update(name: string, info: IdentifierInfo, requireAccepted?: true): Promise<HabState>;
113
+ update(name: string, info: IdentifierInfo, requireAccepted: false): Promise<HabState | PendingHabState>;
114
+ update(name: string, info: IdentifierInfo, requireAccepted: boolean): Promise<HabState | PendingHabState>;
100
115
  /**
101
116
  * Create a managed identifier
102
117
  * @async
@@ -4,6 +4,7 @@ import { b, Ilks, Serials, Vrsn_1_0 } from "../core/core.js";
4
4
  import { Tholder } from "../core/tholder.js";
5
5
  import { MtrDex } from "../core/matter.js";
6
6
  import { parseRangeHeaders } from "../core/httping.js";
7
+ import { requireKeyState, } from "../core/keyState.js";
7
8
  /** Identifier */
8
9
  export class Identifier {
9
10
  /**
@@ -37,31 +38,26 @@ export class Identifier {
37
38
  aids: aids,
38
39
  };
39
40
  }
40
- /**
41
- * Get information for a managed identifier
42
- * @async
43
- * @param {string} name Prefix or alias of the identifier
44
- * @returns {Promise<HabState>} A promise to the identifier information
45
- */
46
- async get(name) {
47
- const path = `/identifiers/${encodeURIComponent(name)}`;
41
+ async get(name, requireAccepted = true) {
42
+ const path = `/identifiers/${name}`;
48
43
  const data = null;
49
44
  const method = 'GET';
50
45
  const res = await this.client.fetch(path, method, data);
51
- return await res.json();
46
+ const hab = await res.json();
47
+ if (requireAccepted) {
48
+ requireKeyState(hab);
49
+ }
50
+ return hab;
52
51
  }
53
- /**
54
- * Update managed identifier
55
- * @async
56
- * @param {string} name Prefix or alias of the identifier
57
- * @param {IdentifierInfo} info Information to update for the given identifier
58
- * @returns {Promise<HabState>} A promise to the identifier information after updating
59
- */
60
- async update(name, info) {
52
+ async update(name, info, requireAccepted = true) {
61
53
  const path = `/identifiers/${name}`;
62
54
  const method = 'PUT';
63
55
  const res = await this.client.fetch(path, method, info);
64
- return await res.json();
56
+ const hab = await res.json();
57
+ if (requireAccepted) {
58
+ requireKeyState(hab);
59
+ }
60
+ return hab;
65
61
  }
66
62
  /**
67
63
  * Create a managed identifier
@@ -274,7 +270,7 @@ export class Identifier {
274
270
  adds: adds,
275
271
  data: data,
276
272
  });
277
- const sigs = await keeper.sign(b(serder.raw));
273
+ const sigs = await keeper.sign(b(serder.raw), true, undefined, undefined, true);
278
274
  const jsondata = {
279
275
  rot: serder.sad,
280
276
  sigs: sigs,
@@ -1,5 +1,5 @@
1
+ import { Authenticator } from '../core/authing.ts';
1
2
  import { components } from '../../types/keria-api-schema.ts';
2
- import { Authenticater } from '../core/authing.ts';
3
3
  import { ExternalModule, IdentifierManagerFactory } from '../core/keeping.ts';
4
4
  import { Tier } from '../core/salter.ts';
5
5
  import { Identifier } from './aiding.ts';
@@ -13,6 +13,10 @@ import { Exchanges } from './exchanging.ts';
13
13
  import { Groups } from './grouping.ts';
14
14
  import { Notifications } from './notifying.ts';
15
15
  export type AgentResourceResult = components['schemas']['AgentResourceResult'];
16
+ /** Cancellation options for booting or connecting a Signify client. */
17
+ export interface ConnectionOptions {
18
+ signal?: AbortSignal;
19
+ }
16
20
  declare class State {
17
21
  agent: any | null;
18
22
  controller: any | null;
@@ -20,6 +24,10 @@ declare class State {
20
24
  pidx: number;
21
25
  constructor();
22
26
  }
27
+ export declare enum AuthMode {
28
+ SignedHeaders = "SIGNED_HEADERS",
29
+ ESSR = "ESSR"
30
+ }
23
31
  /**
24
32
  * An in-memory key manager that can connect to a KERIA Agent and use it to
25
33
  * receive messages and act as a proxy for multi-signature operations and delegation operations.
@@ -30,11 +38,12 @@ export declare class SignifyClient {
30
38
  bran: string;
31
39
  pidx: number;
32
40
  agent: Agent | null;
33
- authn: Authenticater | null;
41
+ authn: Authenticator | null;
34
42
  manager: IdentifierManagerFactory | null;
35
43
  tier: Tier;
36
44
  bootUrl: string;
37
45
  exteralModules: ExternalModule[];
46
+ authMode: AuthMode;
38
47
  private _identifiers;
39
48
  private _operations;
40
49
  private _keyEvents;
@@ -60,34 +69,40 @@ export declare class SignifyClient {
60
69
  * @param {string} bootUrl KERIA boot interface URL
61
70
  * @param {ExternalModule[]} externalModules list of external modules to load
62
71
  */
63
- constructor(url: string, bran: string, tier?: Tier, bootUrl?: string, externalModules?: ExternalModule[]);
64
- get data(): (string | number | Authenticater | null)[];
72
+ constructor(url: string, bran: string, tier?: Tier, bootUrl?: string, externalModules?: ExternalModule[], authMode?: AuthMode);
73
+ get data(): (string | number | Authenticator | null)[];
65
74
  /**
66
75
  * Boot a KERIA agent
67
76
  * @async
77
+ * @param {ConnectionOptions} [options] Cancellation options
68
78
  * @returns {Promise<Response>} A promise to the result of the boot
69
79
  */
70
- boot(): Promise<Response>;
80
+ boot(options?: ConnectionOptions): Promise<Response>;
71
81
  /**
72
82
  * Get state of the agent and the client
73
83
  * @async
84
+ * @param {ConnectionOptions} [options] Cancellation options
74
85
  * @returns {Promise<Response>} A promise to the state
75
86
  */
76
- state(): Promise<State>;
77
- /** Connect to a KERIA agent
87
+ state(options?: ConnectionOptions): Promise<State>;
88
+ /**
89
+ * Connect to an existing KERIA Agent and restore its in-memory Controller,
90
+ * load agent state, and initialize authenticated client services.
91
+ *
78
92
  * @async
93
+ * @param {ConnectionOptions} [options] Cancellation options
79
94
  */
80
- connect(): Promise<void>;
95
+ connect(options?: ConnectionOptions): Promise<void>;
81
96
  /**
82
97
  * Fetch a resource from the KERIA agent
83
98
  * @async
84
99
  * @param {string} path Path to the resource
85
100
  * @param {string} method HTTP method
86
- * @param {any} data Data to be sent in the body of the resource
101
+ * @param {unknown} [data] Data to be sent in the body of the resource
87
102
  * @param {Headers} [extraHeaders] Optional extra headers to be sent with the request
88
103
  * @returns {Promise<Response>} A promise to the result of the fetch
89
104
  */
90
- fetch(path: string, method: string, data: any, extraHeaders?: Headers): Promise<Response>;
105
+ fetch(path: string, method: string, data?: unknown, extraHeaders?: Headers): Promise<Response>;
91
106
  /**
92
107
  * Create a Signed Request to fetch a resource from an external URL with headers signed by an AID
93
108
  * @async
@@ -106,22 +121,10 @@ export declare class SignifyClient {
106
121
  /**
107
122
  * Approve the delegation of the client AID to the KERIA agent
108
123
  * @async
124
+ * @param {ConnectionOptions} [options] Cancellation options
109
125
  * @returns {Promise<Response>} A promise to the result of the approval
110
126
  */
111
- approveDelegation(): Promise<Response>;
112
- /**
113
- * Save old client passcode in KERIA agent
114
- * @async
115
- * @param {string} passcode Passcode to be saved
116
- * @returns {Promise<Response>} A promise to the result of the save
117
- */
118
- saveOldPasscode(passcode: string): Promise<Response>;
119
- /**
120
- * Delete a saved passcode from KERIA agent
121
- * @async
122
- * @returns {Promise<Response>} A promise to the result of the deletion
123
- */
124
- deletePasscode(): Promise<Response>;
127
+ private approveDelegation;
125
128
  /**
126
129
  * Rotate the client AID
127
130
  * @async
@@ -1,6 +1,7 @@
1
- import { Authenticater } from "../core/authing.js";
2
- import { HEADER_SIG_TIME } from "../core/httping.js";
1
+ import { EssrAuthenticator, SignedHeaderAuthenticator, } from "../core/authing.js";
2
+ import { HEADER_SIG_SENDER, HEADER_SIG_TIME } from "../core/httping.js";
3
3
  import { IdentifierManagerFactory } from "../core/keeping.js";
4
+ import { CesrNumber } from "../core/number.js";
4
5
  import { Tier } from "../core/salter.js";
5
6
  import { Identifier } from "./aiding.js";
6
7
  import { Contacts, Challenges } from "./contacting.js";
@@ -21,6 +22,16 @@ class State {
21
22
  this.ridx = 0;
22
23
  }
23
24
  }
25
+ export var AuthMode;
26
+ (function (AuthMode) {
27
+ AuthMode["SignedHeaders"] = "SIGNED_HEADERS";
28
+ AuthMode["ESSR"] = "ESSR";
29
+ })(AuthMode || (AuthMode = {}));
30
+ function jsonBody(data) {
31
+ // typed as string, but returns undefined for undefined/functions/symbols
32
+ const json = JSON.stringify(data);
33
+ return json !== null && json !== void 0 ? json : null;
34
+ }
24
35
  /**
25
36
  * An in-memory key manager that can connect to a KERIA Agent and use it to
26
37
  * receive messages and act as a proxy for multi-signature operations and delegation operations.
@@ -34,7 +45,7 @@ export class SignifyClient {
34
45
  * @param {string} bootUrl KERIA boot interface URL
35
46
  * @param {ExternalModule[]} externalModules list of external modules to load
36
47
  */
37
- constructor(url, bran, tier = Tier.low, bootUrl = DEFAULT_BOOT_URL, externalModules = []) {
48
+ constructor(url, bran, tier = Tier.low, bootUrl = DEFAULT_BOOT_URL, externalModules = [], authMode = AuthMode.SignedHeaders) {
38
49
  this._identifiers = new Identifier(this);
39
50
  this._operations = new Operations(this);
40
51
  this._keyEvents = new KeyEvents(this);
@@ -65,6 +76,7 @@ export class SignifyClient {
65
76
  this.tier = tier;
66
77
  this.bootUrl = bootUrl;
67
78
  this.exteralModules = externalModules;
79
+ this.authMode = authMode;
68
80
  }
69
81
  get data() {
70
82
  return [this.url, this.bran, this.pidx, this.authn];
@@ -72,9 +84,10 @@ export class SignifyClient {
72
84
  /**
73
85
  * Boot a KERIA agent
74
86
  * @async
87
+ * @param {ConnectionOptions} [options] Cancellation options
75
88
  * @returns {Promise<Response>} A promise to the result of the boot
76
89
  */
77
- async boot() {
90
+ async boot(options = {}) {
78
91
  var _a, _b, _c, _d;
79
92
  const [evt, sign] = (_b = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.event) !== null && _b !== void 0 ? _b : [];
80
93
  const data = {
@@ -90,17 +103,21 @@ export class SignifyClient {
90
103
  headers: {
91
104
  'Content-Type': 'application/json',
92
105
  },
106
+ signal: options.signal,
93
107
  });
94
108
  }
95
109
  /**
96
110
  * Get state of the agent and the client
97
111
  * @async
112
+ * @param {ConnectionOptions} [options] Cancellation options
98
113
  * @returns {Promise<Response>} A promise to the state
99
114
  */
100
- async state() {
115
+ async state(options = {}) {
101
116
  var _a, _b, _c, _d, _e;
102
117
  const caid = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.pre;
103
- const res = await fetch(this.url + `/agent/${caid}`);
118
+ const res = await fetch(this.url + `/agent/${caid}`, {
119
+ signal: options.signal,
120
+ });
104
121
  if (res.status == 404) {
105
122
  throw new Error(`agent does not exist for controller ${caid}`);
106
123
  }
@@ -112,79 +129,77 @@ export class SignifyClient {
112
129
  state.pidx = (_e = data.pidx) !== null && _e !== void 0 ? _e : 0;
113
130
  return state;
114
131
  }
115
- /** Connect to a KERIA agent
132
+ /**
133
+ * Connect to an existing KERIA Agent and restore its in-memory Controller,
134
+ * load agent state, and initialize authenticated client services.
135
+ *
116
136
  * @async
137
+ * @param {ConnectionOptions} [options] Cancellation options
117
138
  */
118
- async connect() {
119
- const state = await this.state();
139
+ async connect(options = {}) {
140
+ var _a, _b;
141
+ const state = await this.state(options);
120
142
  this.pidx = state.pidx;
121
- //Create controller representing the local client AID
143
+ // Restore the controller from KERIA's authoritative persisted state.
122
144
  this.controller = new Controller(this.bran, this.tier, 0, state.controller);
123
145
  this.controller.ridx = state.ridx !== undefined ? state.ridx : 0;
124
146
  // Create agent representing the AID of KERIA cloud agent
125
147
  this.agent = new Agent(state.agent);
126
- if (this.agent.anchor != this.controller.pre) {
148
+ if (this.agent.anchor !== this.controller.pre) {
127
149
  throw Error('commitment to controller AID missing in agent inception event');
128
150
  }
129
- if (this.controller.serder.sad.s == 0) {
130
- await this.approveDelegation();
151
+ const controllerSequence = (_b = (_a = state.controller) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.s;
152
+ if (typeof controllerSequence !== 'string') {
153
+ throw new Error('KERIA controller state is missing a string sequence number');
154
+ }
155
+ if (new CesrNumber({}, controllerSequence).num === 0) {
156
+ await this.approveDelegation(options);
131
157
  }
132
158
  this.manager = new IdentifierManagerFactory(this.controller.salter, this.exteralModules);
133
- this.authn = new Authenticater(this.controller.signer, this.agent.verfer);
159
+ if (this.authMode === AuthMode.SignedHeaders) {
160
+ this.authn = new SignedHeaderAuthenticator(this.controller.signer, this.agent.verfer);
161
+ }
162
+ else {
163
+ this.authn = new EssrAuthenticator(this.controller.signer, this.agent.verfer);
164
+ }
134
165
  }
135
166
  /**
136
167
  * Fetch a resource from the KERIA agent
137
168
  * @async
138
169
  * @param {string} path Path to the resource
139
170
  * @param {string} method HTTP method
140
- * @param {any} data Data to be sent in the body of the resource
171
+ * @param {unknown} [data] Data to be sent in the body of the resource
141
172
  * @param {Headers} [extraHeaders] Optional extra headers to be sent with the request
142
173
  * @returns {Promise<Response>} A promise to the result of the fetch
143
174
  */
144
175
  async fetch(path, method, data, extraHeaders) {
145
- var _a;
176
+ if (!this.authn) {
177
+ throw new Error('Client needs to call connect first');
178
+ }
146
179
  const headers = new Headers();
147
- let signed_headers = new Headers();
148
- const final_headers = new Headers();
149
- headers.set('Signify-Resource', this.controller.pre);
180
+ headers.set(HEADER_SIG_SENDER, this.controller.pre);
150
181
  headers.set(HEADER_SIG_TIME, new Date().toISOString().replace('Z', '000+00:00'));
151
- headers.set('Content-Type', 'application/json');
152
- const _body = method == 'GET' ? null : JSON.stringify(data);
153
- if (this.authn) {
154
- signed_headers = this.authn.sign(headers, method, path.split('?')[0]);
155
- }
156
- else {
157
- throw new Error('client need to call connect first');
158
- }
159
- signed_headers.forEach((value, key) => {
160
- final_headers.set(key, value);
161
- });
162
- if (extraHeaders !== undefined) {
182
+ if (extraHeaders) {
163
183
  extraHeaders.forEach((value, key) => {
164
- final_headers.append(key, value);
184
+ headers.append(key, value);
165
185
  });
166
186
  }
167
- const res = await fetch(this.url + path, {
168
- method: method,
169
- body: _body,
170
- headers: final_headers,
187
+ const body = method === 'GET' ? null : jsonBody(data);
188
+ if (body) {
189
+ headers.set('Content-Type', 'application/json');
190
+ }
191
+ const baseRequest = new Request(this.url + path, {
192
+ method,
193
+ body,
194
+ headers,
171
195
  });
196
+ const request = await this.authn.prepare(baseRequest, this.controller.pre, this.agent.pre);
197
+ const res = await this.authn.verify(baseRequest, await fetch(request), this.controller.pre, this.agent.pre);
172
198
  if (!res.ok) {
173
199
  const error = await res.text();
174
- const message = `HTTP ${method} ${path} - ${res.status} ${res.statusText} - ${error}`;
175
- throw new Error(message);
176
- }
177
- const isSameAgent = ((_a = this.agent) === null || _a === void 0 ? void 0 : _a.pre) === res.headers.get('signify-resource');
178
- if (!isSameAgent) {
179
- throw new Error('message from a different remote agent');
180
- }
181
- const verification = this.authn.verify(res.headers, method, path.split('?')[0]);
182
- if (verification) {
183
- return res;
184
- }
185
- else {
186
- throw new Error('response verification failed');
200
+ throw new Error(`HTTP ${method} ${path} - ${res.status} ${res.statusText} - ${error}`);
187
201
  }
202
+ return res;
188
203
  }
189
204
  /**
190
205
  * Create a Signed Request to fetch a resource from an external URL with headers signed by an AID
@@ -204,65 +219,44 @@ export class SignifyClient {
204
219
  var _a;
205
220
  const hab = await this.identifiers().get(aidName);
206
221
  const keeper = this.manager.get(hab);
207
- const authenticator = new Authenticater(keeper.signers[0], keeper.signers[0].verfer);
222
+ const authenticator = new SignedHeaderAuthenticator(keeper.signers[0], keeper.signers[0].verfer);
208
223
  const headers = new Headers(req.headers);
209
- headers.set('Signify-Resource', hab['prefix']);
224
+ headers.set(HEADER_SIG_SENDER, hab.prefix);
210
225
  headers.set(HEADER_SIG_TIME, new Date().toISOString().replace('Z', '000+00:00'));
211
- const signed_headers = authenticator.sign(new Headers(headers), (_a = req.method) !== null && _a !== void 0 ? _a : 'GET', new URL(url).pathname);
212
- req.headers = signed_headers;
213
- return new Request(url, req);
226
+ return await authenticator.prepare(new Request(url, {
227
+ headers,
228
+ method: (_a = req.method) !== null && _a !== void 0 ? _a : 'GET',
229
+ body: req.body,
230
+ }), hab.prefix, hab.prefix);
214
231
  }
215
232
  /**
216
233
  * Approve the delegation of the client AID to the KERIA agent
217
234
  * @async
235
+ * @param {ConnectionOptions} [options] Cancellation options
218
236
  * @returns {Promise<Response>} A promise to the result of the approval
219
237
  */
220
- async approveDelegation() {
221
- const sigs = this.controller.approveDelegation(this.agent);
238
+ async approveDelegation(options = {}) {
239
+ var _a;
240
+ (_a = options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
241
+ const approval = this.controller.approveDelegation(this.agent);
222
242
  const data = {
223
- ixn: this.controller.serder.sad,
224
- sigs: sigs,
243
+ ixn: approval.event.sad,
244
+ sigs: approval.signatures,
225
245
  };
226
- return await fetch(this.url + '/agent/' + this.controller.pre + '?type=ixn', {
246
+ const response = await fetch(this.url + '/agent/' + this.controller.pre + '?type=ixn', {
227
247
  method: 'PUT',
228
248
  body: JSON.stringify(data),
229
249
  headers: {
230
250
  'Content-Type': 'application/json',
231
251
  },
252
+ signal: options.signal,
232
253
  });
233
- }
234
- /**
235
- * Save old client passcode in KERIA agent
236
- * @async
237
- * @param {string} passcode Passcode to be saved
238
- * @returns {Promise<Response>} A promise to the result of the save
239
- */
240
- async saveOldPasscode(passcode) {
241
- var _a;
242
- const caid = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.pre;
243
- const body = { salt: passcode };
244
- return await fetch(this.url + '/salt/' + caid, {
245
- method: 'PUT',
246
- body: JSON.stringify(body),
247
- headers: {
248
- 'Content-Type': 'application/json',
249
- },
250
- });
251
- }
252
- /**
253
- * Delete a saved passcode from KERIA agent
254
- * @async
255
- * @returns {Promise<Response>} A promise to the result of the deletion
256
- */
257
- async deletePasscode() {
258
- var _a;
259
- const caid = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.pre;
260
- return await fetch(this.url + '/salt/' + caid, {
261
- method: 'DELETE',
262
- headers: {
263
- 'Content-Type': 'application/json',
264
- },
265
- });
254
+ if (!response.ok) {
255
+ const body = await response.text();
256
+ const details = body.length > 0 ? ` - ${body}` : '';
257
+ throw new Error(`agent delegation approval failed: ${response.status} ${response.statusText}${details}`);
258
+ }
259
+ return response;
266
260
  }
267
261
  /**
268
262
  * Rotate the client AID
@@ -77,7 +77,10 @@ export declare class Controller {
77
77
  * @param state
78
78
  */
79
79
  constructor(bran: string, tier: Tier, ridx?: number, state?: any | null);
80
- approveDelegation(_agent: Agent): any[];
80
+ approveDelegation(_agent: Agent): {
81
+ event: Serder;
82
+ signatures: any[];
83
+ };
81
84
  get pre(): string;
82
85
  get event(): any[];
83
86
  get verfers(): [];
@@ -107,7 +107,7 @@ export class Controller {
107
107
  new Diger({ code: MtrDex.Blake3_256 }, this.nsigner.verfer.qb64b)
108
108
  .qb64,
109
109
  ];
110
- if (state == null || state['ee']['s'] == 0) {
110
+ if (state === null || state['ee']['s'] === '0') {
111
111
  this.serder = incept({
112
112
  keys: this.keys,
113
113
  isith: '1',
@@ -126,7 +126,7 @@ export class Controller {
126
126
  const seqner = new Seqner({ sn: _agent.sn });
127
127
  const anchor = { i: _agent.pre, s: seqner.snh, d: _agent.said };
128
128
  const sn = new CesrNumber({}, this.serder.sad['s']).num + 1;
129
- this.serder = interact({
129
+ const event = interact({
130
130
  pre: this.serder.pre,
131
131
  dig: this.serder.sad['d'],
132
132
  sn: sn,
@@ -134,7 +134,11 @@ export class Controller {
134
134
  version: Vrsn_1_0,
135
135
  kind: Serials.JSON,
136
136
  });
137
- return [this.signer.sign(this.serder.raw, 0).qb64];
137
+ this.serder = event;
138
+ return {
139
+ event,
140
+ signatures: [this.signer.sign(event.raw, 0).qb64],
141
+ };
138
142
  }
139
143
  get pre() {
140
144
  return this.serder.pre;
@@ -1,6 +1,6 @@
1
1
  import { SignifyClient } from './clienting.ts';
2
2
  import { components } from '../../types/keria-api-schema.ts';
3
- import { OOBIOperation, QueryOperation, EndRoleOperation, WitnessOperation, DelegationOperation, RegistryOperation, LocSchemeOperation, ChallengeOperation, ExchangeOperation, SubmitOperation, DoneOperation, CredentialOperation, GroupOperation, DelegatorOperation, CompletedOOBIOperation, CompletedQueryOperation, CompletedEndRoleOperation, CompletedWitnessOperation, CompletedDelegationOperation, CompletedRegistryOperation, CompletedLocSchemeOperation, CompletedChallengeOperation, CompletedExchangeOperation, CompletedSubmitOperation, CompletedDoneOperation, CompletedCredentialOperation, CompletedGroupOperation, CompletedDelegatorOperation, CompletedOperation } from '../core/keyState.ts';
3
+ import { OOBIOperation, QueryOperation, EndRoleOperation, WitnessOperation, DelegationOperation, RegistryOperation, LocSchemeOperation, ChallengeOperation, ExchangeOperation, SubmitOperation, DoneOperation, CredentialOperation, GroupOperation, DelegatorOperation, CompletedOOBIOperation, CompletedQueryOperation, CompletedEndRoleOperation, CompletedWitnessOperation, CompletedDelegationOperation, CompletedRegistryOperation, CompletedLocSchemeOperation, CompletedChallengeOperation, CompletedExchangeOperation, CompletedSubmitOperation, CompletedDoneOperation, CompletedCredentialOperation, CompletedGroupOperation, CompletedDelegatorOperation, CompletedOperation, EndRole } from '../core/keyState.ts';
4
4
  type OOBI = components['schemas']['OOBI'];
5
5
  type KeyState = components['schemas']['KeyStateRecord'];
6
6
  type KeyEventRecord = components['schemas']['KeyEventRecord'];
@@ -29,6 +29,13 @@ export declare class Oobis {
29
29
  * @returns {Promise<OOBIOperation>} A promise to the long-running operation
30
30
  */
31
31
  resolve(oobi: string, alias?: string): Promise<OOBIOperation>;
32
+ /**
33
+ * Get end roles for an AID by prefix
34
+ * @param {string} aid AID prefix
35
+ * @param {string} [role] Optional role to filter by
36
+ * @returns {Promise<EndRole[]>} A promise to the list of end roles
37
+ */
38
+ endroles(aid: string, role?: string): Promise<EndRole[]>;
32
39
  }
33
40
  export type Operation = OOBIOperation | QueryOperation | EndRoleOperation | WitnessOperation | DelegationOperation | RegistryOperation | LocSchemeOperation | ChallengeOperation | ExchangeOperation | SubmitOperation | DoneOperation | CredentialOperation | GroupOperation | DelegatorOperation;
34
41
  export interface OperationsDeps {
@@ -51,6 +51,17 @@ export class Oobis {
51
51
  const res = await this.client.fetch(path, method, data);
52
52
  return await res.json();
53
53
  }
54
+ /**
55
+ * Get end roles for an AID by prefix
56
+ * @param {string} aid AID prefix
57
+ * @param {string} [role] Optional role to filter by
58
+ * @returns {Promise<EndRole[]>} A promise to the list of end roles
59
+ */
60
+ async endroles(aid, role) {
61
+ const path = role ? `/endroles/${aid}/${role}` : `/endroles/${aid}`;
62
+ const res = await this.client.fetch(path, 'GET', null);
63
+ return await res.json();
64
+ }
54
65
  }
55
66
  /**
56
67
  * Operations