@toa.io/extensions.exposition 1.0.0-alpha.256 → 1.0.0-alpha.258

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 (54) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/components/identity.basic/manifest.toa.yaml +7 -1
  3. package/components/identity.basic/operations/add.js +2 -1
  4. package/components/identity.basic/operations/add.js.map +1 -1
  5. package/components/identity.basic/operations/transit.js +2 -1
  6. package/components/identity.basic/operations/transit.js.map +1 -1
  7. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  8. package/components/identity.basic/operations/types.d.ts +2 -0
  9. package/components/identity.basic/source/add.ts +2 -1
  10. package/components/identity.basic/source/transit.ts +2 -1
  11. package/components/identity.basic/source/types.ts +3 -0
  12. package/components/identity.federation/events/principal.js +2 -2
  13. package/components/identity.federation/manifest.toa.yaml +18 -7
  14. package/components/identity.federation/operations/authenticate.js +13 -15
  15. package/components/identity.federation/operations/authenticate.js.map +1 -1
  16. package/components/identity.federation/operations/create.d.ts +8 -0
  17. package/components/identity.federation/operations/create.js +27 -0
  18. package/components/identity.federation/operations/create.js.map +1 -0
  19. package/components/identity.federation/operations/delete.js +1 -1
  20. package/components/identity.federation/operations/delete.js.map +1 -1
  21. package/components/identity.federation/operations/incept.d.ts +1 -1
  22. package/components/identity.federation/operations/incept.js +3 -26
  23. package/components/identity.federation/operations/incept.js.map +1 -1
  24. package/components/identity.federation/operations/lib/exchange.js +1 -1
  25. package/components/identity.federation/operations/lib/exchange.js.map +1 -1
  26. package/components/identity.federation/operations/lib/index.d.ts +1 -0
  27. package/components/identity.federation/operations/lib/index.js +3 -1
  28. package/components/identity.federation/operations/lib/index.js.map +1 -1
  29. package/components/identity.federation/operations/lib/resolve.d.ts +3 -0
  30. package/components/identity.federation/operations/lib/resolve.js +17 -0
  31. package/components/identity.federation/operations/lib/resolve.js.map +1 -0
  32. package/components/identity.federation/operations/list.js +1 -5
  33. package/components/identity.federation/operations/list.js.map +1 -1
  34. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  35. package/components/identity.federation/operations/types/context.d.ts +2 -5
  36. package/components/identity.federation/operations/types/entity.d.ts +2 -1
  37. package/components/identity.federation/source/authenticate.ts +15 -18
  38. package/components/identity.federation/source/create.ts +39 -0
  39. package/components/identity.federation/source/delete.ts +1 -1
  40. package/components/identity.federation/source/incept.ts +5 -37
  41. package/components/identity.federation/source/lib/exchange.ts +1 -1
  42. package/components/identity.federation/source/lib/index.ts +1 -0
  43. package/components/identity.federation/source/lib/resolve.ts +17 -0
  44. package/components/identity.federation/source/list.test.ts +3 -5
  45. package/components/identity.federation/source/list.ts +1 -8
  46. package/components/identity.federation/source/types/context.ts +2 -6
  47. package/components/identity.federation/source/types/entity.ts +2 -1
  48. package/components/identity.roles/receivers/identity.federation.principal.js +6 -0
  49. package/documentation/credentials.md +5 -2
  50. package/documentation/identity.md +1 -1
  51. package/features/identity.basic.feature +54 -0
  52. package/features/identity.federation.feature +100 -2
  53. package/features/map.feature +2 -1
  54. package/package.json +3 -3
@@ -8,7 +8,7 @@ export interface Context {
8
8
  observe: Observation<Entity>;
9
9
  enumerate: Observation<Entity[], never, Entity>;
10
10
  terminate: Transition<void, void, Entity>;
11
- transit: Call<TransitOutput, TransitInput>;
11
+ transit: Call<Entity, TransitInput>;
12
12
  ensure: Call<Entity>;
13
13
  decode: Call<JWTPayload, string>;
14
14
  };
@@ -27,10 +27,7 @@ export interface TransitInput {
27
27
  readonly authority: string;
28
28
  readonly iss: string;
29
29
  readonly sub: string;
30
- readonly identity?: string;
31
- }
32
- export interface TransitOutput {
33
- id: string;
30
+ readonly identity: string;
34
31
  }
35
32
  interface IdentityTokensRevokeInput {
36
33
  query: Query;
@@ -3,6 +3,7 @@ export interface Entity {
3
3
  authority: string;
4
4
  iss: string;
5
5
  sub: string;
6
- identity?: string;
6
+ identity: string;
7
7
  _created: number;
8
+ _deleted?: number | null;
8
9
  }
@@ -1,6 +1,6 @@
1
1
  import { Err } from 'error-value'
2
- import { decode, exchange } from './lib'
3
- import type { Ctx } from './lib'
2
+ import { newid } from '@toa.io/generic'
3
+ import { resolve } from './lib'
4
4
  import type { JWTPayload } from 'jose'
5
5
  import type { Maybe } from '@toa.io/types'
6
6
  import type { Context, Scheme } from './types'
@@ -8,15 +8,7 @@ import type { Context, Scheme } from './types'
8
8
  export async function effect ({ scheme, authority, credentials }: Input, context: Context): Promise<Maybe<Output>> {
9
9
  context.logs.debug('Authenticating', { scheme, authority, credentials })
10
10
 
11
- const ctx: Ctx = {
12
- trust: context.configuration.trust,
13
- logs: context.logs,
14
- fetch: context.fetch
15
- }
16
-
17
- const claims = scheme === 'bearer'
18
- ? await decode(credentials, ctx)
19
- : await exchange(credentials, ctx)
11
+ const claims = await resolve(scheme, credentials, context)
20
12
 
21
13
  if (claims instanceof Error)
22
14
  return claims
@@ -25,17 +17,22 @@ export async function effect ({ scheme, authority, credentials }: Input, context
25
17
 
26
18
  context.logs.debug('Token claims', claims)
27
19
 
28
- const identity = context.configuration.assert !== false
29
- ? await context.local.ensure({ entity: { authority, iss, sub } })
30
- : await context.local.observe({ query: { criteria: `authority==${authority};iss==${iss};sub==${sub}` } })
20
+ const query = { criteria: `authority==${authority};iss==${iss};sub==${sub}` }
21
+
22
+ const credential = context.configuration.assert !== false
23
+ ? await context.local.ensure({
24
+ query,
25
+ entity: { authority, iss, sub, identity: newid() }
26
+ })
27
+ : await context.local.observe({ query })
31
28
 
32
- if (identity === null)
29
+ if (credential === null)
33
30
  return ERR_NOT_FOUND
34
31
 
35
- if (identity instanceof Error)
36
- return identity
32
+ if (credential instanceof Error)
33
+ return credential
37
34
 
38
- return { identity: { id: identity.identity ?? identity.id, claims } }
35
+ return { identity: { id: credential.identity, claims } }
39
36
  }
40
37
 
41
38
  const ERR_NOT_FOUND = new Err('NOT_FOUND')
@@ -0,0 +1,39 @@
1
+ import { Err } from 'error-value'
2
+ import { resolve } from './lib'
3
+ import type { Context, Entity, Scheme } from './types'
4
+
5
+ export async function effect (input: Input, context: Context): Promise<Entity | Error> {
6
+ const claims = await resolve(input.scheme, input.credentials, context)
7
+
8
+ if (claims instanceof Error)
9
+ return claims
10
+
11
+ const { iss, sub } = claims
12
+
13
+ const existent = await context.local.observe({
14
+ query: { criteria: `authority==${input.authority};iss==${iss};sub==${sub}`, deleted: true }
15
+ })
16
+
17
+ const record = { authority: input.authority, iss, sub, identity: input.id }
18
+
19
+ if (existent === null)
20
+ return await context.local.transit({ input: record })
21
+
22
+ if (existent._deleted === undefined || existent._deleted === null)
23
+ return existent.identity === input.id ? existent : ERR_EXISTS
24
+
25
+ // a deleted record still occupies the unique index, so the transition revives it
26
+ return await context.local.transit({
27
+ input: record,
28
+ query: { id: existent.id, deleted: true }
29
+ })
30
+ }
31
+
32
+ export interface Input {
33
+ authority: string
34
+ scheme: Scheme
35
+ credentials: string
36
+ id: string
37
+ }
38
+
39
+ const ERR_EXISTS = new Err('EXISTS', 'Federation credentials are associated with another Identity')
@@ -3,7 +3,7 @@ import type { Context } from './types'
3
3
  export async function effect ({ authority, identity, credential }: Input, context: Context): Promise<void | null> {
4
4
  const object = await context.local.observe({ query: { id: credential } })
5
5
 
6
- if (object === null || object.authority !== authority || (object.identity ?? object.id) !== identity)
6
+ if (object === null || object.authority !== authority || object.identity !== identity)
7
7
  return null
8
8
 
9
9
  return await context.local.terminate({ query: { id: credential } })
@@ -1,51 +1,19 @@
1
- import { Err } from 'error-value'
2
- import { decode, exchange, type Ctx } from './lib'
3
- import type { Request } from '@toa.io/types'
4
- import type { Context, TransitInput, Scheme } from './types'
1
+ import { effect as create } from './create'
2
+ import type { Context, Scheme } from './types'
5
3
 
6
4
  export async function effect (input: Input, context: Context): Promise<Output | Error> {
7
- const ctx: Ctx = {
8
- trust: context.configuration.trust,
9
- logs: context.logs,
10
- fetch: context.fetch
11
- }
5
+ const credential = await create(input, context)
12
6
 
13
- const claims = input.scheme === 'bearer'
14
- ? await decode(input.credentials, ctx)
15
- : await exchange(input.credentials, ctx)
16
-
17
- if (claims instanceof Error)
18
- return claims
19
-
20
- const { iss, sub } = claims
21
-
22
- if (input.id === undefined) {
23
- const request: Request<TransitInput> = { input: { authority: input.authority, iss, sub } }
24
-
25
- return await context.local.transit(request)
26
- }
27
-
28
- const existent = await context.local.observe({
29
- query: { criteria: `authority==${input.authority};iss==${iss};sub==${sub}` }
30
- })
31
-
32
- if (existent !== null)
33
- return (existent.identity ?? existent.id) === input.id ? { id: input.id } : ERR_EXISTS
34
-
35
- return await context.local.transit({
36
- input: { authority: input.authority, iss, sub, identity: input.id }
37
- })
7
+ return credential instanceof Error ? credential : { id: credential.identity }
38
8
  }
39
9
 
40
10
  export interface Input {
41
11
  authority: string
42
12
  scheme: Scheme
43
13
  credentials: string
44
- id?: string
14
+ id: string
45
15
  }
46
16
 
47
17
  export interface Output {
48
18
  id: string
49
19
  }
50
-
51
- const ERR_EXISTS = new Err('EXISTS', 'Federation credentials are associated with another Identity')
@@ -95,7 +95,7 @@ async function sign (trust: Trust): Promise<string> {
95
95
  const signature = trust.signature!
96
96
  const aud = Array.isArray(trust.aud) ? trust.aud[0] : trust.aud!
97
97
  const now = Math.floor(Date.now() / 1000)
98
- const key = await jose.importPKCS8(atob(signature.key), 'ES256')
98
+ const key = await jose.importPKCS8(signature.key, 'ES256')
99
99
 
100
100
  return await new jose.SignJWT({})
101
101
  .setProtectedHeader({ alg: 'ES256', kid: signature.kid })
@@ -1,3 +1,4 @@
1
1
  export { decode } from './decode'
2
2
  export { exchange } from './exchange'
3
+ export { resolve } from './resolve'
3
4
  export { type Ctx } from './Ctx'
@@ -0,0 +1,17 @@
1
+ import { decode } from './decode'
2
+ import { exchange } from './exchange'
3
+ import type { Ctx } from './Ctx'
4
+ import type { Payload } from './Payload'
5
+ import type { Context, Scheme } from '../types'
6
+
7
+ export async function resolve (scheme: Scheme, credentials: string, context: Context): Promise<Payload | Error> {
8
+ const ctx: Ctx = {
9
+ trust: context.configuration.trust,
10
+ logs: context.logs,
11
+ fetch: context.fetch
12
+ }
13
+
14
+ return scheme === 'bearer'
15
+ ? await decode(credentials, ctx)
16
+ : await exchange(credentials, ctx)
17
+ }
@@ -1,18 +1,16 @@
1
1
  import { computation } from './list'
2
2
 
3
- it('lists indexed credentials and a legacy associated credential', async () => {
3
+ it('lists indexed credentials', async () => {
4
4
  const current = { id: 'credential', authority: 'nex', identity: 'identity', iss: 'apple', sub: '1', _created: 2 }
5
- const legacy = { id: 'identity', authority: 'nex', iss: 'google', sub: '2', _created: 1 }
6
5
 
7
6
  const context = {
8
7
  local: {
9
- enumerate: jest.fn(async () => [current]),
10
- observe: jest.fn(async () => legacy)
8
+ enumerate: jest.fn(async () => [current])
11
9
  }
12
10
  }
13
11
 
14
12
  await expect(computation({ authority: 'nex', identity: 'identity' }, context as never))
15
- .resolves.toEqual([current, legacy])
13
+ .resolves.toEqual([current])
16
14
  expect(context.local.enumerate).toHaveBeenCalledWith({
17
15
  query: {
18
16
  criteria: 'authority==nex;identity==identity',
@@ -1,7 +1,7 @@
1
1
  import type { Context, Entity } from './types'
2
2
 
3
3
  export async function computation ({ authority, identity }: Input, context: Context): Promise<Entity[]> {
4
- const objects = await context.local.enumerate({
4
+ return await context.local.enumerate({
5
5
  query: {
6
6
  criteria: `authority==${authority};identity==${identity}`,
7
7
  projection: ['iss'],
@@ -9,13 +9,6 @@ export async function computation ({ authority, identity }: Input, context: Cont
9
9
  limit: 100
10
10
  }
11
11
  })
12
-
13
- const legacy = await context.local.observe({ query: { id: identity } })
14
-
15
- if (legacy !== null && legacy.authority === authority && legacy.identity === undefined)
16
- objects.push(legacy)
17
-
18
- return objects.sort((a, b) => b._created - a._created)
19
12
  }
20
13
 
21
14
  interface Input {
@@ -9,7 +9,7 @@ export interface Context {
9
9
  observe: Observation<Entity>
10
10
  enumerate: Observation<Entity[], never, Entity>
11
11
  terminate: Transition<void, void, Entity>
12
- transit: Call<TransitOutput, TransitInput>
12
+ transit: Call<Entity, TransitInput>
13
13
  ensure: Call<Entity>
14
14
  decode: Call<JWTPayload, string>
15
15
  }
@@ -30,11 +30,7 @@ export interface TransitInput {
30
30
  readonly authority: string
31
31
  readonly iss: string
32
32
  readonly sub: string
33
- readonly identity?: string
34
- }
35
-
36
- export interface TransitOutput {
37
- id: string
33
+ readonly identity: string
38
34
  }
39
35
 
40
36
  interface IdentityTokensRevokeInput {
@@ -3,6 +3,7 @@ export interface Entity {
3
3
  authority: string
4
4
  iss: string
5
5
  sub: string
6
- identity?: string
6
+ identity: string
7
7
  _created: number
8
+ _deleted?: number | null
8
9
  }
@@ -0,0 +1,6 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * @param {{ identity: string }} payload
5
+ */
6
+ exports.request = (payload) => ({ input: { id: payload.identity } })
@@ -57,12 +57,15 @@ constraints, and principal configuration.
57
57
 
58
58
  ## Federated credentials
59
59
 
60
- - `POST /identity/federation/:identity/` associates credentials from a trusted issuer.
60
+ - `POST /identity/federation/:identity/` associates credentials from a trusted issuer and returns
61
+ the associated credential as it is listed.
61
62
  - `GET /identity/federation/:identity/` lists federated credentials.
62
63
  - `DELETE /identity/federation/:identity/:credential/` removes one federated credential.
63
64
 
65
+ If the credentials are already associated with the Identity, the existing credential is returned.
66
+
64
67
  An Identity can have credentials from multiple issuers and can have multiple subjects from the
65
- same issuer. The `:credential` segment is the `id` returned by either listing resource. Federation
68
+ same issuer. The `:credential` segment is the `id` returned by any of these resources. Federation
66
69
  resources are provider-independent; issuer-specific authorization flows remain the responsibility
67
70
  of the application.
68
71
 
@@ -131,7 +131,7 @@ configuration:
131
131
  signature:
132
132
  iss: team-id
133
133
  kid: key-id
134
- key: $APPLE_PRIVATE_KEY
134
+ key: $APPLE_PRIVATE_KEY # PKCS8 PEM, as in the .p8 file
135
135
  ```
136
136
 
137
137
  ### OTP scheme
@@ -474,3 +474,57 @@ Feature: Basic authentication
474
474
 
475
475
  code: EXISTS
476
476
  """
477
+
478
+ Scenario: Adding basic credentials after they have been deleted
479
+ Given transient identity
480
+ When the following request is received:
481
+ """
482
+ POST /identity/basic/${{ identity.id }}/ HTTP/1.1
483
+ host: nex.toa.io
484
+ authorization: Token ${{ identity.token }}
485
+ content-type: application/yaml
486
+
487
+ username: developer
488
+ password: secret#1234
489
+ """
490
+ Then the following reply is sent:
491
+ """
492
+ 201 Created
493
+ """
494
+ When the following request is received:
495
+ """
496
+ DELETE /identity/basic/${{ identity.id }}/ HTTP/1.1
497
+ host: nex.toa.io
498
+ authorization: Token ${{ identity.token }}
499
+ """
500
+ Then the following reply is sent:
501
+ """
502
+ 200 OK
503
+ """
504
+ When the following request is received:
505
+ """
506
+ POST /identity/basic/${{ identity.id }}/ HTTP/1.1
507
+ host: nex.toa.io
508
+ authorization: Token ${{ identity.token }}
509
+ content-type: application/yaml
510
+
511
+ username: painter
512
+ password: secret#4321
513
+ """
514
+ Then the following reply is sent:
515
+ """
516
+ 201 Created
517
+ """
518
+ When the following request is received:
519
+ """
520
+ GET /identity/ HTTP/1.1
521
+ host: nex.toa.io
522
+ authorization: Basic cGFpbnRlcjpzZWNyZXQjNDMyMQ==
523
+ accept: application/yaml
524
+ """
525
+ Then the following reply is sent:
526
+ """
527
+ 200 OK
528
+
529
+ id: ${{ identity.id }}
530
+ """
@@ -54,6 +54,21 @@ Feature: Identity Federation
54
54
 
55
55
  id: ${{ User.id }}
56
56
  """
57
+ # credential id is detached from the Identity
58
+ When the following request is received:
59
+ """
60
+ GET /identity/federation/${{ User.id }}/ HTTP/1.1
61
+ host: nex.toa.io
62
+ authorization: Bearer ${{ User.id_token }}
63
+ accept: application/yaml
64
+ """
65
+ Then the following reply is sent:
66
+ """
67
+ 200 OK
68
+
69
+ - id: ${{ User.credential }}
70
+ iss: http://localhost:44444
71
+ """
57
72
 
58
73
  Scenario: Creating an Identity using inception
59
74
  Given the `identity.federation` configuration:
@@ -88,8 +103,10 @@ Feature: Identity Federation
88
103
  """
89
104
  201 Created
90
105
  authorization: Token ${{ Bill.token }}
106
+
107
+ id: ${{ Bill.id }}
91
108
  """
92
- # check that both tokens authenticate the created federation identity
109
+ # check that both tokens authenticate the created user's Identity
93
110
  When the following request is received:
94
111
  """
95
112
  GET /identity/ HTTP/1.1
@@ -100,6 +117,8 @@ Feature: Identity Federation
100
117
  Then the following reply is sent:
101
118
  """
102
119
  200 OK
120
+
121
+ id: ${{ Bill.id }}
103
122
  roles: []
104
123
  """
105
124
  When the following request is received:
@@ -113,8 +132,24 @@ Feature: Identity Federation
113
132
  """
114
133
  200 OK
115
134
 
135
+ id: ${{ Bill.id }}
116
136
  roles: []
117
137
  """
138
+ # credential id is detached from the Identity
139
+ When the following request is received:
140
+ """
141
+ GET /identity/federation/${{ Bill.id }}/ HTTP/1.1
142
+ host: nex.toa.io
143
+ authorization: Bearer ${{ Bill.id_token }}
144
+ accept: application/yaml
145
+ """
146
+ Then the following reply is sent:
147
+ """
148
+ 200 OK
149
+
150
+ - id: ${{ Bill.credential }}
151
+ iss: http://localhost:44444
152
+ """
118
153
  And the following request is received:
119
154
  # same credentials
120
155
  """
@@ -214,6 +249,64 @@ Feature: Identity Federation
214
249
  content-type: application/yaml
215
250
  accept: application/yaml
216
251
 
252
+ scheme: bearer
253
+ credentials: ${{ Bob.id_token }}
254
+ """
255
+ Then the following reply is sent:
256
+ """
257
+ 201 Created
258
+
259
+ id: ${{ Bob.credential }}
260
+ iss: http://localhost:44444
261
+ """
262
+ # the created credential is listed as is
263
+ When the following request is received:
264
+ """
265
+ GET /identity/federation/${{ Bob.id }}/ HTTP/1.1
266
+ host: nex.toa.io
267
+ authorization: Basic #{{ basic Bob }}
268
+ accept: application/yaml
269
+ """
270
+ Then the following reply is sent:
271
+ """
272
+ 200 OK
273
+
274
+ - id: ${{ Bob.credential }}
275
+ iss: http://localhost:44444
276
+ """
277
+ And the following request is received:
278
+ """
279
+ GET /identity/ HTTP/1.1
280
+ host: nex.toa.io
281
+ authorization: Bearer ${{ Bob.id_token }}
282
+ accept: application/yaml
283
+ """
284
+ Then the following reply is sent:
285
+ """
286
+ 200 OK
287
+
288
+ id: ${{ Bob.id }}
289
+ """
290
+ # delete the federation credential
291
+ When the following request is received:
292
+ """
293
+ DELETE /identity/federation/${{ Bob.id }}/${{ Bob.credential }}/ HTTP/1.1
294
+ host: nex.toa.io
295
+ authorization: Basic #{{ basic Bob }}
296
+ """
297
+ Then the following reply is sent:
298
+ """
299
+ 200 OK
300
+ """
301
+ # add the same federation again
302
+ When the following request is received:
303
+ """
304
+ POST /identity/federation/${{ Bob.id }}/ HTTP/1.1
305
+ host: nex.toa.io
306
+ authorization: Basic #{{ basic Bob }}
307
+ content-type: application/yaml
308
+ accept: application/yaml
309
+
217
310
  scheme: bearer
218
311
  credentials: ${{ Bob.id_token }}
219
312
  """
@@ -268,7 +361,12 @@ Feature: Identity Federation
268
361
  signature:
269
362
  iss: io.toa.nex.id
270
363
  kid: key-id
271
- key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZzl4OURhdHdIMEdaSFNDbzkKVE1IVFZYeWVZMFlROHFiNzNqSFYydjRNc3llaFJBTkNBQVF3YVlsbmEyaFNWM0cvUklsTkxWNDFsZzhQbTRLZgpIZkN1S0tpdzNCSUpUblNBckFNSkxTeTF2WXdTSU1IejcyMG1rbVdUcld1UWtranZrRHBaeGZSdgotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t
364
+ key: |
365
+ -----BEGIN PRIVATE KEY-----
366
+ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9x9DatwH0GZHSCo9
367
+ TMHTVXyeY0YQ8qb73jHV2v4MsyehRANCAAQwaYlna2hSV3G/RIlNLV41lg8Pm4Kf
368
+ HfCuKKiw3BIJTnSArAMJLSy1vYwSIMHz720mkmWTrWuQkkjvkDpZxfRv
369
+ -----END PRIVATE KEY-----
272
370
  """
273
371
  And auth code for Bob is issued for https://web.toa.io/callback/
274
372
  When the following request is received:
@@ -269,6 +269,7 @@ Feature: HTTP context mapping
269
269
  """yaml
270
270
  trust:
271
271
  - iss: http://localhost:44444
272
+ assert: false
272
273
  """
273
274
  And the `pots` is running with the following manifest:
274
275
  """yaml
@@ -299,8 +300,8 @@ Feature: HTTP context mapping
299
300
  201 Created
300
301
 
301
302
  id: ${{ id }}
302
- title: ${{ random.email }}
303
303
  volume: 1.5
304
+ title: ${{ random.email }}
304
305
  """
305
306
 
306
307
  Scenario: Mapping non-exposed properties
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/extensions.exposition",
3
- "version": "1.0.0-alpha.256",
3
+ "version": "1.0.0-alpha.258",
4
4
  "description": "Toa Exposition",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@simplewebauthn/server": "13.3.2",
21
- "@toa.io/core": "1.0.0-alpha.254",
21
+ "@toa.io/core": "1.0.0-alpha.257",
22
22
  "@toa.io/generic": "1.0.0-alpha.254",
23
23
  "@toa.io/schemas": "1.0.0-alpha.254",
24
24
  "bcryptjs": "3.0.3",
@@ -62,5 +62,5 @@
62
62
  },
63
63
  "testEnvironment": "node"
64
64
  },
65
- "gitHead": "a8990df97f971060686bd70a965f78e98070a983"
65
+ "gitHead": "35a7cb8922be6921239562ebb3ab833893b5bd6e"
66
66
  }