@toa.io/extensions.exposition 1.0.0-alpha.251 → 1.0.0-alpha.253

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 (59) hide show
  1. package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -1
  2. package/components/identity.basic/manifest.toa.yaml +16 -0
  3. package/components/identity.basic/operations/delete.d.ts +7 -0
  4. package/components/identity.basic/operations/delete.js +11 -0
  5. package/components/identity.basic/operations/delete.js.map +1 -0
  6. package/components/identity.basic/operations/info.d.ts +10 -0
  7. package/components/identity.basic/operations/info.js +11 -0
  8. package/components/identity.basic/operations/info.js.map +1 -0
  9. package/components/identity.basic/operations/tsconfig.tsbuildinfo +1 -1
  10. package/components/identity.basic/operations/types.d.ts +2 -1
  11. package/components/identity.basic/source/delete.ts +15 -0
  12. package/components/identity.basic/source/info.ts +19 -0
  13. package/components/identity.basic/source/types.ts +2 -1
  14. package/components/identity.credentials/manifest.toa.yaml +57 -0
  15. package/components/identity.credentials/operations/list.d.ts +51 -0
  16. package/components/identity.credentials/operations/list.js +32 -0
  17. package/components/identity.credentials/operations/list.js.map +1 -0
  18. package/components/identity.credentials/operations/tsconfig.tsbuildinfo +1 -0
  19. package/components/identity.credentials/source/list.test.ts +47 -0
  20. package/components/identity.credentials/source/list.ts +87 -0
  21. package/components/identity.credentials/tsconfig.json +7 -0
  22. package/components/identity.federation/manifest.toa.yaml +35 -1
  23. package/components/identity.federation/operations/authenticate.js +1 -1
  24. package/components/identity.federation/operations/authenticate.js.map +1 -1
  25. package/components/identity.federation/operations/delete.d.ts +8 -0
  26. package/components/identity.federation/operations/delete.js +11 -0
  27. package/components/identity.federation/operations/delete.js.map +1 -0
  28. package/components/identity.federation/operations/incept.js +14 -4
  29. package/components/identity.federation/operations/incept.js.map +1 -1
  30. package/components/identity.federation/operations/list.d.ts +7 -0
  31. package/components/identity.federation/operations/list.js +18 -0
  32. package/components/identity.federation/operations/list.js.map +1 -0
  33. package/components/identity.federation/operations/tsconfig.tsbuildinfo +1 -1
  34. package/components/identity.federation/operations/types/context.d.ts +5 -5
  35. package/components/identity.federation/operations/types/entity.d.ts +2 -0
  36. package/components/identity.federation/source/authenticate.ts +1 -1
  37. package/components/identity.federation/source/delete.ts +16 -0
  38. package/components/identity.federation/source/incept.ts +18 -4
  39. package/components/identity.federation/source/list.test.ts +23 -0
  40. package/components/identity.federation/source/list.ts +23 -0
  41. package/components/identity.federation/source/types/context.ts +5 -6
  42. package/components/identity.federation/source/types/entity.ts +2 -0
  43. package/components/identity.keys/operations/tsconfig.tsbuildinfo +1 -1
  44. package/components/identity.otp/operations/tsconfig.tsbuildinfo +1 -1
  45. package/components/identity.passkeys/operations/tsconfig.tsbuildinfo +1 -1
  46. package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
  47. package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
  48. package/documentation/components.md +3 -0
  49. package/documentation/credentials.md +85 -0
  50. package/documentation/identity.md +3 -0
  51. package/documentation/passkeys.md +1 -0
  52. package/features/credentials.feature +106 -0
  53. package/features/steps/Database.ts +6 -2
  54. package/package.json +6 -5
  55. package/readme.md +19 -0
  56. package/source/HTTP/Server.ts +1 -0
  57. package/transpiled/HTTP/Server.js +1 -0
  58. package/transpiled/HTTP/Server.js.map +1 -1
  59. package/transpiled/tsconfig.tsbuildinfo +1 -1
@@ -1,12 +1,14 @@
1
1
  import type { JWTPayload } from 'jose';
2
- import type { Call, Observation, Query, telemetry } from '@toa.io/types';
2
+ import type { Call, Observation, Query, telemetry, Transition } from '@toa.io/types';
3
3
  import type { Entity } from './entity';
4
4
  import type { Configuration } from './configuration';
5
5
  export interface Context {
6
6
  local: {
7
7
  observe: Observation<Entity>;
8
+ enumerate: Observation<Entity[], never, Entity>;
9
+ terminate: Transition<void, void, Entity>;
8
10
  transit: Call<TransitOutput, TransitInput>;
9
- ensure: Call<EnsureOutput>;
11
+ ensure: Call<Entity>;
10
12
  decode: Call<JWTPayload, string>;
11
13
  };
12
14
  remote: {
@@ -23,13 +25,11 @@ export interface TransitInput {
23
25
  readonly authority: string;
24
26
  readonly iss: string;
25
27
  readonly sub: string;
28
+ readonly identity?: string;
26
29
  }
27
30
  export interface TransitOutput {
28
31
  id: string;
29
32
  }
30
- export interface EnsureOutput {
31
- id: string;
32
- }
33
33
  interface IdentityTokensRevokeInput {
34
34
  query: Query;
35
35
  }
@@ -3,4 +3,6 @@ export interface Entity {
3
3
  authority: string;
4
4
  iss: string;
5
5
  sub: string;
6
+ identity?: string;
7
+ _created: number;
6
8
  }
@@ -34,7 +34,7 @@ export async function effect ({ scheme, authority, credentials }: Input, context
34
34
  if (identity instanceof Error)
35
35
  return identity
36
36
 
37
- return { identity: { id: identity.id, claims } }
37
+ return { identity: { id: identity.identity ?? identity.id, claims } }
38
38
  }
39
39
 
40
40
  const ERR_NOT_FOUND = new Err('NOT_FOUND')
@@ -0,0 +1,16 @@
1
+ import type { Context } from './types'
2
+
3
+ export async function effect ({ authority, identity, id }: Input, context: Context): Promise<void | null> {
4
+ const object = await context.local.observe({ query: { id } })
5
+
6
+ if (object === null || object.authority !== authority || (object.identity ?? object.id) !== identity)
7
+ return null
8
+
9
+ return await context.local.terminate({ query: { id } })
10
+ }
11
+
12
+ interface Input {
13
+ authority: string
14
+ identity: string
15
+ id: string
16
+ }
@@ -1,3 +1,4 @@
1
+ import { Err } from 'error-value'
1
2
  import { decode, exchange, type Ctx } from './lib'
2
3
  import type { Request } from '@toa.io/types'
3
4
  import type { Context, TransitInput, Scheme } from './types'
@@ -16,12 +17,23 @@ export async function effect (input: Input, context: Context): Promise<Output |
16
17
  return claims
17
18
 
18
19
  const { iss, sub } = claims
19
- const request: Request<TransitInput> = { input: { authority: input.authority, iss, sub } }
20
20
 
21
- if (input.id !== undefined)
22
- request.query = { id: input.id }
21
+ if (input.id === undefined) {
22
+ const request: Request<TransitInput> = { input: { authority: input.authority, iss, sub } }
23
23
 
24
- return await context.local.transit(request)
24
+ return await context.local.transit(request)
25
+ }
26
+
27
+ const existent = await context.local.observe({
28
+ query: { criteria: `authority==${input.authority};iss==${iss};sub==${sub}` }
29
+ })
30
+
31
+ if (existent !== null)
32
+ return (existent.identity ?? existent.id) === input.id ? { id: input.id } : ERR_EXISTS
33
+
34
+ return await context.local.transit({
35
+ input: { authority: input.authority, iss, sub, identity: input.id }
36
+ })
25
37
  }
26
38
 
27
39
  export interface Input {
@@ -34,3 +46,5 @@ export interface Input {
34
46
  export interface Output {
35
47
  id: string
36
48
  }
49
+
50
+ const ERR_EXISTS = new Err('EXISTS', 'Federation credentials are associated with another Identity')
@@ -0,0 +1,23 @@
1
+ import { computation } from './list'
2
+
3
+ it('lists indexed credentials and a legacy associated credential', async () => {
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
+
7
+ const context = {
8
+ local: {
9
+ enumerate: jest.fn(async () => [current]),
10
+ observe: jest.fn(async () => legacy)
11
+ }
12
+ }
13
+
14
+ await expect(computation({ authority: 'nex', identity: 'identity' }, context as never))
15
+ .resolves.toEqual([current, legacy])
16
+ expect(context.local.enumerate).toHaveBeenCalledWith({
17
+ query: {
18
+ criteria: 'authority==nex;identity==identity',
19
+ projection: ['iss'],
20
+ sort: ['_created:desc']
21
+ }
22
+ })
23
+ })
@@ -0,0 +1,23 @@
1
+ import type { Context, Entity } from './types'
2
+
3
+ export async function computation ({ authority, identity }: Input, context: Context): Promise<Entity[]> {
4
+ const objects = await context.local.enumerate({
5
+ query: {
6
+ criteria: `authority==${authority};identity==${identity}`,
7
+ projection: ['iss'],
8
+ sort: ['_created:desc']
9
+ }
10
+ })
11
+
12
+ const legacy = await context.local.observe({ query: { id: identity } })
13
+
14
+ if (legacy !== null && legacy.authority === authority && legacy.identity === undefined)
15
+ objects.push(legacy)
16
+
17
+ return objects.sort((a, b) => b._created - a._created)
18
+ }
19
+
20
+ interface Input {
21
+ authority: string
22
+ identity: string
23
+ }
@@ -1,13 +1,15 @@
1
1
  import type { JWTPayload } from 'jose'
2
- import type { Call, Observation, Query, telemetry } from '@toa.io/types'
2
+ import type { Call, Observation, Query, telemetry, Transition } from '@toa.io/types'
3
3
  import type { Entity } from './entity'
4
4
  import type { Configuration } from './configuration'
5
5
 
6
6
  export interface Context {
7
7
  local: {
8
8
  observe: Observation<Entity>
9
+ enumerate: Observation<Entity[], never, Entity>
10
+ terminate: Transition<void, void, Entity>
9
11
  transit: Call<TransitOutput, TransitInput>
10
- ensure: Call<EnsureOutput>
12
+ ensure: Call<Entity>
11
13
  decode: Call<JWTPayload, string>
12
14
  }
13
15
  remote: {
@@ -25,16 +27,13 @@ export interface TransitInput {
25
27
  readonly authority: string
26
28
  readonly iss: string
27
29
  readonly sub: string
30
+ readonly identity?: string
28
31
  }
29
32
 
30
33
  export interface TransitOutput {
31
34
  id: string
32
35
  }
33
36
 
34
- export interface EnsureOutput {
35
- id: string
36
- }
37
-
38
37
  interface IdentityTokensRevokeInput {
39
38
  query: Query
40
39
  }
@@ -3,4 +3,6 @@ export interface Entity {
3
3
  authority: string
4
4
  iss: string
5
5
  sub: string
6
+ identity?: string
7
+ _created: number
6
8
  }