@toa.io/extensions.exposition 1.0.0-alpha.282 → 1.0.0-alpha.283
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/CHANGELOG.md +27 -0
- package/components/exposition.octets/manifest.toa.yaml +11 -0
- package/components/exposition.octets/types/index.d.ts +3 -0
- package/components/exposition.octets/types/toa.d.ts +41 -0
- package/components/identity.bans/types/index.d.ts +3 -0
- package/components/identity.bans/types/toa.d.ts +34 -0
- package/components/identity.basic/manifest.toa.yaml +13 -2
- package/components/identity.basic/operations/add.d.ts +3 -3
- package/components/identity.basic/operations/authenticate.d.ts +2 -2
- package/components/identity.basic/operations/check.d.ts +1 -1
- package/components/identity.basic/operations/delete.d.ts +2 -2
- package/components/identity.basic/operations/incept.d.ts +2 -2
- package/components/identity.basic/operations/info.d.ts +1 -1
- package/components/identity.basic/operations/transit.d.ts +4 -3
- package/components/identity.basic/operations/transit.js +2 -1
- package/components/identity.basic/operations/transit.js.map +1 -1
- package/components/identity.basic/source/add.ts +3 -3
- package/components/identity.basic/source/authenticate.ts +2 -2
- package/components/identity.basic/source/check.ts +1 -1
- package/components/identity.basic/source/delete.ts +2 -2
- package/components/identity.basic/source/incept.ts +2 -2
- package/components/identity.basic/source/info.ts +1 -1
- package/components/identity.basic/source/transit.ts +6 -4
- package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/types/index.d.ts +21 -0
- package/components/identity.basic/types/toa.d.ts +121 -0
- package/components/identity.clients/manifest.toa.yaml +243 -0
- package/components/identity.clients/operations/describe.d.ts +27 -0
- package/components/identity.clients/operations/describe.js +44 -0
- package/components/identity.clients/operations/describe.js.map +1 -0
- package/components/identity.clients/operations/lib/Context.d.ts +29 -0
- package/components/identity.clients/operations/lib/Context.js +2 -0
- package/components/identity.clients/operations/lib/Context.js.map +1 -0
- package/components/identity.clients/operations/lib/Entity.d.ts +29 -0
- package/components/identity.clients/operations/lib/Entity.js +2 -0
- package/components/identity.clients/operations/lib/Entity.js.map +1 -0
- package/components/identity.clients/operations/lib/canonical.d.ts +11 -0
- package/components/identity.clients/operations/lib/canonical.js +24 -0
- package/components/identity.clients/operations/lib/canonical.js.map +1 -0
- package/components/identity.clients/operations/lib/cimd.d.ts +8 -0
- package/components/identity.clients/operations/lib/cimd.js +86 -0
- package/components/identity.clients/operations/lib/cimd.js.map +1 -0
- package/components/identity.clients/operations/lib/errors.d.ts +7 -0
- package/components/identity.clients/operations/lib/errors.js +5 -0
- package/components/identity.clients/operations/lib/errors.js.map +1 -0
- package/components/identity.clients/operations/lib/index.d.ts +6 -0
- package/components/identity.clients/operations/lib/index.js +7 -0
- package/components/identity.clients/operations/lib/index.js.map +1 -0
- package/components/identity.clients/operations/lib/redirect.d.ts +10 -0
- package/components/identity.clients/operations/lib/redirect.js +32 -0
- package/components/identity.clients/operations/lib/redirect.js.map +1 -0
- package/components/identity.clients/operations/register.d.ts +37 -0
- package/components/identity.clients/operations/register.js +84 -0
- package/components/identity.clients/operations/register.js.map +1 -0
- package/components/identity.clients/source/describe.ts +65 -0
- package/components/identity.clients/source/lib/Context.ts +38 -0
- package/components/identity.clients/source/lib/Entity.ts +31 -0
- package/components/identity.clients/source/lib/canonical.test.ts +43 -0
- package/components/identity.clients/source/lib/canonical.ts +27 -0
- package/components/identity.clients/source/lib/cimd.test.ts +120 -0
- package/components/identity.clients/source/lib/cimd.ts +107 -0
- package/components/identity.clients/source/lib/errors.ts +4 -0
- package/components/identity.clients/source/lib/index.ts +6 -0
- package/components/identity.clients/source/lib/redirect.test.ts +41 -0
- package/components/identity.clients/source/lib/redirect.ts +35 -0
- package/components/identity.clients/source/register.ts +125 -0
- package/components/identity.clients/tsconfig.json +10 -0
- package/components/identity.clients/tsconfig.tsbuildinfo +1 -0
- package/components/identity.clients/types/index.d.ts +3 -0
- package/components/identity.clients/types/toa.d.ts +109 -0
- package/components/identity.credentials/operations/list.d.ts +2 -1
- package/components/identity.credentials/operations/list.js.map +1 -1
- package/components/identity.credentials/source/list.ts +2 -1
- package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
- package/components/identity.credentials/types/index.d.ts +3 -0
- package/components/identity.credentials/types/toa.d.ts +30 -0
- package/components/identity.federation/manifest.toa.yaml +37 -1
- package/components/identity.federation/operations/authenticate.d.ts +1 -1
- package/components/identity.federation/operations/lib/Ctx.d.ts +2 -2
- package/components/identity.federation/operations/lib/decode.js +22 -8
- package/components/identity.federation/operations/lib/decode.js.map +1 -1
- package/components/identity.federation/operations/lib/errors.d.ts +7 -0
- package/components/identity.federation/operations/lib/errors.js +4 -0
- package/components/identity.federation/operations/lib/errors.js.map +1 -1
- package/components/identity.federation/operations/lib/exchange.js +11 -6
- package/components/identity.federation/operations/lib/exchange.js.map +1 -1
- package/components/identity.federation/operations/types/configuration.d.ts +1 -1
- package/components/identity.federation/operations/types/context.d.ts +3 -2
- package/components/identity.federation/source/authenticate.ts +1 -1
- package/components/identity.federation/source/lib/Ctx.ts +2 -2
- package/components/identity.federation/source/lib/decode.ts +25 -9
- package/components/identity.federation/source/lib/errors.ts +5 -0
- package/components/identity.federation/source/lib/exchange.ts +11 -7
- package/components/identity.federation/source/types/configuration.ts +1 -1
- package/components/identity.federation/source/types/context.ts +3 -2
- package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/types/index.d.ts +3 -0
- package/components/identity.federation/types/toa.d.ts +127 -0
- package/components/identity.grants/manifest.toa.yaml +245 -0
- package/components/identity.grants/operations/authorize.d.ts +35 -0
- package/components/identity.grants/operations/authorize.js +54 -0
- package/components/identity.grants/operations/authorize.js.map +1 -0
- package/components/identity.grants/operations/exchange.d.ts +37 -0
- package/components/identity.grants/operations/exchange.js +89 -0
- package/components/identity.grants/operations/exchange.js.map +1 -0
- package/components/identity.grants/operations/lib/code.d.ts +15 -0
- package/components/identity.grants/operations/lib/code.js +30 -0
- package/components/identity.grants/operations/lib/code.js.map +1 -0
- package/components/identity.grants/operations/lib/identify.d.ts +6 -0
- package/components/identity.grants/operations/lib/identify.js +15 -0
- package/components/identity.grants/operations/lib/identify.js.map +1 -0
- package/components/identity.grants/operations/lib/index.d.ts +3 -0
- package/components/identity.grants/operations/lib/index.js +3 -0
- package/components/identity.grants/operations/lib/index.js.map +1 -0
- package/components/identity.grants/operations/list.d.ts +13 -0
- package/components/identity.grants/operations/list.js +18 -0
- package/components/identity.grants/operations/list.js.map +1 -0
- package/components/identity.grants/operations/revoke.d.ts +18 -0
- package/components/identity.grants/operations/revoke.js +25 -0
- package/components/identity.grants/operations/revoke.js.map +1 -0
- package/components/identity.grants/source/authorize.ts +90 -0
- package/components/identity.grants/source/exchange.ts +130 -0
- package/components/identity.grants/source/lib/code.ts +39 -0
- package/components/identity.grants/source/lib/identify.ts +16 -0
- package/components/identity.grants/source/lib/index.ts +3 -0
- package/components/identity.grants/source/list.ts +28 -0
- package/components/identity.grants/source/revoke.ts +38 -0
- package/components/identity.grants/tsconfig.json +10 -0
- package/components/identity.grants/tsconfig.tsbuildinfo +1 -0
- package/components/identity.grants/types/index.d.ts +60 -0
- package/components/identity.grants/types/toa.d.ts +108 -0
- package/components/identity.keys/manifest.toa.yaml +1 -0
- package/components/identity.keys/operations/create.d.ts +1 -1
- package/components/identity.keys/operations/revoke.d.ts +1 -1
- package/components/identity.keys/source/create.ts +1 -1
- package/components/identity.keys/source/revoke.ts +1 -1
- package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.keys/types/index.d.ts +3 -0
- package/components/identity.keys/types/toa.d.ts +47 -0
- package/components/identity.otp/operations/lib/Context.d.ts +4 -2
- package/components/identity.otp/source/lib/Context.ts +4 -2
- package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/types/index.d.ts +3 -0
- package/components/identity.otp/types/toa.d.ts +56 -0
- package/components/identity.passkeys/manifest.toa.yaml +3 -0
- package/components/identity.passkeys/operations/authenticate.d.ts +1 -1
- package/components/identity.passkeys/operations/challenge.d.ts +1 -1
- package/components/identity.passkeys/operations/create.d.ts +1 -1
- package/components/identity.passkeys/operations/types/Context.d.ts +2 -1
- package/components/identity.passkeys/operations/use.d.ts +1 -1
- package/components/identity.passkeys/source/authenticate.ts +1 -1
- package/components/identity.passkeys/source/challenge.ts +1 -1
- package/components/identity.passkeys/source/create.ts +1 -1
- package/components/identity.passkeys/source/types/Context.ts +2 -1
- package/components/identity.passkeys/source/use.ts +1 -1
- package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.passkeys/types/index.d.ts +3 -0
- package/components/identity.passkeys/types/toa.d.ts +120 -0
- package/components/identity.roles/operations/principal.d.ts +1 -1
- package/components/identity.roles/source/principal.ts +1 -1
- package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/types/index.d.ts +3 -0
- package/components/identity.roles/types/toa.d.ts +43 -0
- package/components/identity.tokens/manifest.toa.yaml +34 -3
- package/components/identity.tokens/operations/authenticate.d.ts +2 -1
- package/components/identity.tokens/operations/authenticate.js +8 -0
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/decrypt.d.ts +2 -1
- package/components/identity.tokens/operations/decrypt.js +2 -2
- package/components/identity.tokens/operations/decrypt.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.d.ts +2 -1
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/issue.d.ts +2 -1
- package/components/identity.tokens/operations/issue.js +2 -1
- package/components/identity.tokens/operations/issue.js.map +1 -1
- package/components/identity.tokens/operations/lib/form.d.ts +8 -0
- package/components/identity.tokens/operations/lib/form.js +24 -0
- package/components/identity.tokens/operations/lib/form.js.map +1 -0
- package/components/identity.tokens/operations/lib/index.d.ts +2 -1
- package/components/identity.tokens/operations/lib/index.js +1 -1
- package/components/identity.tokens/operations/lib/index.js.map +1 -1
- package/components/identity.tokens/source/authenticate.test.ts +8 -5
- package/components/identity.tokens/source/authenticate.ts +12 -1
- package/components/identity.tokens/source/decrypt.test.ts +1 -1
- package/components/identity.tokens/source/decrypt.ts +4 -3
- package/components/identity.tokens/source/encrypt.test.ts +1 -1
- package/components/identity.tokens/source/encrypt.ts +2 -1
- package/components/identity.tokens/source/issue.test.ts +71 -0
- package/components/identity.tokens/source/issue.ts +4 -2
- package/components/identity.tokens/source/lib/form.test.ts +25 -0
- package/components/identity.tokens/source/lib/form.ts +31 -0
- package/components/identity.tokens/source/lib/index.ts +2 -1
- package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/types/index.d.ts +61 -0
- package/components/identity.tokens/types/toa.d.ts +113 -0
- package/documentation/cache.md +10 -1
- package/documentation/consent.md +101 -0
- package/documentation/identity.md +3 -1
- package/documentation/io.md +36 -2
- package/documentation/oauth.md +179 -0
- package/documentation/protocol.md +4 -0
- package/features/auth.bearer.feature +120 -0
- package/features/cache.feature +46 -0
- package/features/oauth.clients.feature +195 -0
- package/features/oauth.discovery.feature +165 -0
- package/features/oauth.grants.feature +286 -0
- package/features/steps/Gateway.ts +6 -1
- package/features/steps/Parameters.ts +4 -0
- package/features/steps/components/echo/manifest.toa.yaml +2 -0
- package/features/steps/components/octets.tester/manifest.toa.yaml +2 -0
- package/features/steps/components/octets.tester/operations/redirect.js +6 -1
- package/features/steps/components/users/manifest.toa.yaml +1 -0
- package/package.json +8 -6
- package/readme.md +3 -0
- package/schemas/annotation.cos.yaml +30 -0
- package/source/Annotation.ts +23 -0
- package/source/Factory.ts +1 -1
- package/source/HTTP/Server.ts +9 -5
- package/source/HTTP/formats/form.ts +21 -0
- package/source/HTTP/formats/index.ts +17 -2
- package/source/HTTP/messages.test.ts +25 -1
- package/source/HTTP/messages.ts +10 -3
- package/source/Interception.ts +8 -2
- package/source/deployment.ts +4 -1
- package/source/directives/auth/Authorization.ts +46 -19
- package/source/directives/auth/Incept.ts +14 -9
- package/source/directives/auth/schemes.test.ts +8 -4
- package/source/directives/auth/schemes.ts +22 -9
- package/source/directives/auth/types.ts +5 -2
- package/source/directives/cache/Cache.ts +13 -4
- package/source/directives/cache/Control.ts +0 -3
- package/source/directives/flow/Fetch.ts +1 -1
- package/source/directives/index.ts +2 -1
- package/source/directives/io/IO.ts +2 -0
- package/source/directives/io/Output.ts +4 -1
- package/source/directives/io/Status.test.ts +84 -0
- package/source/directives/io/Status.ts +46 -0
- package/source/directives/oauth/Discovery.ts +76 -0
- package/source/directives/oauth/documents.ts +113 -0
- package/source/directives/oauth/index.ts +3 -0
- package/source/directives/octets/Delete.ts +1 -1
- package/source/directives/octets/Get.ts +1 -1
- package/source/directives/octets/Workflow.ts +1 -1
- package/source/directives/octets/workflows/Execution.ts +1 -1
- package/source/index.ts +6 -0
- package/source/octets.d.ts +17 -0
- package/source/userland.ts +47 -0
- package/transpiled/Annotation.d.ts +17 -0
- package/transpiled/Factory.js +1 -1
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +4 -1
- package/transpiled/HTTP/Server.js +4 -3
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/formats/form.d.ts +9 -0
- package/transpiled/HTTP/formats/form.js +18 -0
- package/transpiled/HTTP/formats/form.js.map +1 -0
- package/transpiled/HTTP/formats/index.d.ts +10 -2
- package/transpiled/HTTP/formats/index.js +10 -0
- package/transpiled/HTTP/formats/index.js.map +1 -1
- package/transpiled/HTTP/messages.d.ts +6 -0
- package/transpiled/HTTP/messages.js +3 -3
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Interception.d.ts +4 -1
- package/transpiled/Interception.js +4 -2
- package/transpiled/Interception.js.map +1 -1
- package/transpiled/deployment.js +2 -0
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Authorization.d.ts +1 -1
- package/transpiled/directives/auth/Authorization.js +38 -18
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Incept.d.ts +1 -1
- package/transpiled/directives/auth/Incept.js +11 -7
- package/transpiled/directives/auth/Incept.js.map +1 -1
- package/transpiled/directives/auth/schemes.d.ts +16 -4
- package/transpiled/directives/auth/schemes.js +20 -8
- package/transpiled/directives/auth/schemes.js.map +1 -1
- package/transpiled/directives/auth/types.d.ts +4 -2
- package/transpiled/directives/cache/Cache.js +9 -2
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/cache/Control.js +0 -2
- package/transpiled/directives/cache/Control.js.map +1 -1
- package/transpiled/directives/index.js +2 -1
- package/transpiled/directives/index.js.map +1 -1
- package/transpiled/directives/io/IO.js +2 -0
- package/transpiled/directives/io/IO.js.map +1 -1
- package/transpiled/directives/io/Output.js +4 -1
- package/transpiled/directives/io/Output.js.map +1 -1
- package/transpiled/directives/io/Status.d.ts +19 -0
- package/transpiled/directives/io/Status.js +34 -0
- package/transpiled/directives/io/Status.js.map +1 -0
- package/transpiled/directives/oauth/Discovery.d.ts +23 -0
- package/transpiled/directives/oauth/Discovery.js +58 -0
- package/transpiled/directives/oauth/Discovery.js.map +1 -0
- package/transpiled/directives/oauth/documents.d.ts +9 -0
- package/transpiled/directives/oauth/documents.js +82 -0
- package/transpiled/directives/oauth/documents.js.map +1 -0
- package/transpiled/directives/oauth/index.d.ts +2 -0
- package/transpiled/directives/oauth/index.js +3 -0
- package/transpiled/directives/oauth/index.js.map +1 -0
- package/transpiled/index.d.ts +2 -0
- package/transpiled/userland.d.ts +39 -0
- package/transpiled/userland.js +7 -0
- package/transpiled/userland.js.map +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/components/identity.basic/operations/types.d.ts +0 -61
- package/components/identity.basic/operations/types.js +0 -2
- package/components/identity.basic/operations/types.js.map +0 -1
- package/components/identity.basic/source/types.ts +0 -69
- package/components/identity.tokens/operations/lib/types.d.ts +0 -88
- package/components/identity.tokens/operations/lib/types.js +0 -2
- package/components/identity.tokens/operations/lib/types.js.map +0 -1
- package/components/identity.tokens/source/lib/types.ts +0 -102
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Component } from '@toa.io/core'
|
|
2
|
-
import { type Maybe } from '@toa.io/
|
|
2
|
+
import { type Maybe } from '@toa.io/core'
|
|
3
3
|
import { type Parameter } from '../../RTD/index.js'
|
|
4
4
|
import type * as http from '../../HTTP/index.js'
|
|
5
5
|
import type * as io from '../../io.js'
|
|
@@ -23,6 +23,9 @@ export interface Identity {
|
|
|
23
23
|
roles?: string[]
|
|
24
24
|
permissions?: Record<string, string[]>
|
|
25
25
|
scheme: string | null // null for transient identities
|
|
26
|
+
|
|
27
|
+
/** The component that verified the credentials; none for a transient identity. */
|
|
28
|
+
provider?: Remote
|
|
26
29
|
refresh: boolean
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -43,6 +46,6 @@ export type AuthenticationResult = Maybe<{ identity: Identity, refresh: boolean
|
|
|
43
46
|
export type Scheme = 'basic' | 'token' | 'bearer' | 'code' | 'otp'
|
|
44
47
|
export type Remote = 'basic' | 'federation' | 'tokens' | 'roles' | 'bans' | 'otp'
|
|
45
48
|
export type Discovery = Record<Remote, Promise<Component>>
|
|
46
|
-
export type
|
|
49
|
+
export type Components = Partial<Record<Remote, Component>>
|
|
47
50
|
|
|
48
51
|
export type Create = (name: string, value: any, ...args: any[]) => Directive
|
|
@@ -23,14 +23,23 @@ export class Cache implements DirectiveFamily<Directive> {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public async settle (directives: Directive[], context: AuthenticatedContext, response: http.OutgoingMessage): Promise<void> {
|
|
26
|
-
const
|
|
26
|
+
const directive = directives[0]
|
|
27
|
+
|
|
28
|
+
response.headers ??= new Headers()
|
|
29
|
+
|
|
30
|
+
// `cache:exact` sets what it is given, whatever the method: whether a reply may be
|
|
31
|
+
// stored at all is not a question about the method's cacheability, and a token
|
|
32
|
+
// endpoint answers a POST it must not have kept
|
|
33
|
+
if (directive instanceof Exact) {
|
|
34
|
+
directive.set(context, response.headers)
|
|
27
35
|
|
|
28
|
-
if (method !== 'GET' && method !== 'HEAD')
|
|
29
36
|
return
|
|
37
|
+
}
|
|
30
38
|
|
|
31
|
-
const
|
|
39
|
+
const method = context.request.method
|
|
32
40
|
|
|
33
|
-
|
|
41
|
+
if (method !== 'GET' && method !== 'HEAD')
|
|
42
|
+
return
|
|
34
43
|
|
|
35
44
|
if (directive === undefined) {
|
|
36
45
|
if (context.identity !== null && !Control.disabled(response.headers)) {
|
|
@@ -22,9 +22,6 @@ export class Control implements Directive {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
public set (context: AuthenticatedContext, headers: Headers): void {
|
|
25
|
-
if (!['GET', 'HEAD', 'OPTIONS'].includes(context.request.method))
|
|
26
|
-
return
|
|
27
|
-
|
|
28
25
|
this.control ??= this.resolve(context)
|
|
29
26
|
|
|
30
27
|
if (Control.disabled(headers))
|
|
@@ -5,7 +5,7 @@ import { NotFound } from '../../HTTP/index.js'
|
|
|
5
5
|
import type { Directive } from './types.js'
|
|
6
6
|
import type { ReadableStream } from 'node:stream/web'
|
|
7
7
|
import type { Remotes } from '../../Remotes.js'
|
|
8
|
-
import type { Maybe } from '@toa.io/
|
|
8
|
+
import type { Maybe } from '@toa.io/core'
|
|
9
9
|
import type { Component } from '@toa.io/core'
|
|
10
10
|
import type { Output } from '../../io.js'
|
|
11
11
|
import type { Input } from '../octets/types.js'
|
|
@@ -7,8 +7,9 @@ import { io } from './io/index.js'
|
|
|
7
7
|
import { map } from './map/index.js'
|
|
8
8
|
import { req } from './require/index.js'
|
|
9
9
|
import { flow } from './flow/index.js'
|
|
10
|
+
import { discovery } from './oauth/index.js'
|
|
10
11
|
import type { DirectiveFamily } from '../RTD/index.js'
|
|
11
12
|
import type { Interceptor } from '../Interception.js'
|
|
12
13
|
|
|
13
14
|
export const families: DirectiveFamily[] = [authorization, io, cache, map, req, flow, octets, dev]
|
|
14
|
-
export const interceptors: Interceptor[] = [cors]
|
|
15
|
+
export const interceptors: Interceptor[] = [cors, discovery]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Output } from './Output.js'
|
|
2
2
|
import { Input } from './Input.js'
|
|
3
3
|
import { Throttle } from './Throttle.js'
|
|
4
|
+
import { Status } from './Status.js'
|
|
4
5
|
import { Sync } from './lib/throttle/index.js'
|
|
5
6
|
import type * as http from '../../HTTP/index.js'
|
|
6
7
|
import type { Parameter, DirectiveFamily } from '../../RTD/index.js'
|
|
@@ -72,6 +73,7 @@ export class IO implements DirectiveFamily<Directive> {
|
|
|
72
73
|
const constructors: Record<string, Constructor> = {
|
|
73
74
|
input: Input,
|
|
74
75
|
output: Output,
|
|
76
|
+
status: Status,
|
|
75
77
|
throttle: Throttle
|
|
76
78
|
}
|
|
77
79
|
|
|
@@ -35,7 +35,10 @@ export class Output implements Directive {
|
|
|
35
35
|
|
|
36
36
|
private restriction (context: Context) {
|
|
37
37
|
return (message: OutgoingMessage): void => {
|
|
38
|
-
|
|
38
|
+
// what the gateway built is its own — a code and a message — and a restriction has
|
|
39
|
+
// nothing to say about it; everything else is a reply the operation returned, and is
|
|
40
|
+
// restricted whatever status it carries
|
|
41
|
+
const error = message.authentic === true
|
|
39
42
|
const stream = message.body instanceof Stream
|
|
40
43
|
const none = message.body === undefined || message.body === null
|
|
41
44
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
4
|
+
import { Status } from './Status.js'
|
|
5
|
+
import { Output } from './Output.js'
|
|
6
|
+
import type { Input as Context } from '../../io.js'
|
|
7
|
+
import type { OutgoingMessage } from '../../HTTP/index.js'
|
|
8
|
+
|
|
9
|
+
const status = new Status('status')
|
|
10
|
+
|
|
11
|
+
function context (): Context {
|
|
12
|
+
return { pipelines: { body: [], response: [] }, url: { pathname: '/' } } as unknown as Context
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
it('should take the status from the property and remove it', () => {
|
|
16
|
+
const response: OutgoingMessage = { body: { status: 400, error: 'invalid_request' } }
|
|
17
|
+
|
|
18
|
+
status.settle(context(), response)
|
|
19
|
+
|
|
20
|
+
assert.equal(response.status, 400)
|
|
21
|
+
assert.deepEqual(response.body, { error: 'invalid_request' })
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should leave a reply that states no status alone', () => {
|
|
25
|
+
const response: OutgoingMessage = { body: { id: 'x' } }
|
|
26
|
+
|
|
27
|
+
status.settle(context(), response)
|
|
28
|
+
|
|
29
|
+
assert.equal(response.status, undefined)
|
|
30
|
+
assert.deepEqual(response.body, { id: 'x' })
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should refuse a status that is not one', () => {
|
|
34
|
+
for (const value of ['400', null, {}, true])
|
|
35
|
+
assert.throws(() => {
|
|
36
|
+
status.settle(context(), { body: { status: value } } as OutgoingMessage)
|
|
37
|
+
}, /`io:status` expects 'status' to be a number/)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should refuse a declaration that is not a property name', () => {
|
|
41
|
+
for (const value of [1, null, {}, ['status']])
|
|
42
|
+
assert.throws(() => Status.validate(value), /`io:status` must be a string/)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should have a reply it named the status of restricted, whatever that status is', () => {
|
|
46
|
+
for (const stated of [200, 400]) {
|
|
47
|
+
const ctx = context()
|
|
48
|
+
const output = new Output(['code', 'error'])
|
|
49
|
+
|
|
50
|
+
output.preflight(ctx, [])
|
|
51
|
+
|
|
52
|
+
const response: OutgoingMessage = {
|
|
53
|
+
body: { status: stated, code: 'SplxlO', error: 'invalid_grant', secret: 'x' }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
status.settle(ctx, response)
|
|
57
|
+
|
|
58
|
+
for (const transform of ctx.pipelines.response)
|
|
59
|
+
transform(response)
|
|
60
|
+
|
|
61
|
+
assert.equal(response.status, stated)
|
|
62
|
+
assert.deepEqual(response.body, { code: 'SplxlO', error: 'invalid_grant' })
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('should leave a failure the gateway built alone, on such a route too', () => {
|
|
67
|
+
const ctx = context()
|
|
68
|
+
const output = new Output(['code'])
|
|
69
|
+
|
|
70
|
+
output.preflight(ctx, [])
|
|
71
|
+
|
|
72
|
+
// what `Server.fail` builds out of an exception, on a route that also declares `io:status`
|
|
73
|
+
const response: OutgoingMessage = {
|
|
74
|
+
status: 422,
|
|
75
|
+
authentic: true,
|
|
76
|
+
body: { code: 'NOT_FOUND', message: 'nope' }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
for (const transform of ctx.pipelines.response)
|
|
80
|
+
transform(response)
|
|
81
|
+
|
|
82
|
+
assert.deepEqual(response.body, { code: 'NOT_FOUND', message: 'nope' },
|
|
83
|
+
'a code and a message are not what a restriction has anything to say about')
|
|
84
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import type { Directive } from './Directive.js'
|
|
3
|
+
import type * as http from '../../HTTP/index.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The status of the reply, taken from a property of what the operation returned and removed
|
|
7
|
+
* from it — an outcome the operation knows and the transport does not, like a protocol that
|
|
8
|
+
* states its error as a body rather than as a status of its own.
|
|
9
|
+
*
|
|
10
|
+
* Settled rather than transformed, so the status is set before anything reads it. A reply of
|
|
11
|
+
* 300 or above is left as the operation built it, which `io:output` does not restrict: a
|
|
12
|
+
* failure and a success are different shapes, and one list of permitted properties does not
|
|
13
|
+
* describe both.
|
|
14
|
+
*/
|
|
15
|
+
export class Status implements Directive {
|
|
16
|
+
private readonly property: string
|
|
17
|
+
|
|
18
|
+
public constructor (property: unknown) {
|
|
19
|
+
this.property = property as string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public static validate (value: unknown): asserts value is string {
|
|
23
|
+
assert.ok(typeof value === 'string', '`io:status` must be a string')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public preflight (): void {
|
|
27
|
+
// nothing to do until the operation has answered
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public settle (_: unknown, response: http.OutgoingMessage): void {
|
|
31
|
+
const body: unknown = response.body
|
|
32
|
+
|
|
33
|
+
if (body === null || typeof body !== 'object' || !(this.property in body))
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
const value: unknown = (body as Record<string, unknown>)[this.property]
|
|
37
|
+
|
|
38
|
+
assert.ok(typeof value === 'number',
|
|
39
|
+
`\`io:status\` expects '${this.property}' to be a number`)
|
|
40
|
+
|
|
41
|
+
response.status = value
|
|
42
|
+
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
44
|
+
delete (body as Record<string, unknown>)[this.property]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { documents, type Documents } from './documents.js'
|
|
2
|
+
import type * as http from '../../HTTP/index.js'
|
|
3
|
+
import type { Input, Output } from '../../io.js'
|
|
4
|
+
import type { Interceptor } from '../../Interception.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* What a client reads before it can authenticate: where the authorization server is, and
|
|
8
|
+
* what this resource expects. Both are fixed paths a specification names, both must be
|
|
9
|
+
* answered to anyone, and both are a function of the annotation alone — nothing is read to
|
|
10
|
+
* build them, so they are built once per authority and served as they are.
|
|
11
|
+
*
|
|
12
|
+
* An interceptor rather than a route because `auth` runs before any directive: a client
|
|
13
|
+
* re-reading discovery while holding a stale token would have it verified, and then be
|
|
14
|
+
* refused a document that has to be public.
|
|
15
|
+
*/
|
|
16
|
+
export class Discovery implements Interceptor {
|
|
17
|
+
/**
|
|
18
|
+
* A map, because the key is the request's authority and an unconfigured host is passed
|
|
19
|
+
* through as itself: `Host: constructor` names something a plain object answers on its own.
|
|
20
|
+
*/
|
|
21
|
+
private readonly authorities = new Map<string, Documents>()
|
|
22
|
+
|
|
23
|
+
public mount (options: http.Options): void {
|
|
24
|
+
this.authorities.clear()
|
|
25
|
+
|
|
26
|
+
if (options.oauth === undefined)
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
for (const [authority, host] of Object.entries(options.authorities))
|
|
30
|
+
this.authorities.set(authority, documents(origin(host), options.oauth))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public reset (): void {
|
|
34
|
+
this.authorities.clear()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public intercept (input: Input): Output {
|
|
38
|
+
const known = this.authorities.get(input.authority)
|
|
39
|
+
|
|
40
|
+
if (known === undefined)
|
|
41
|
+
return null
|
|
42
|
+
|
|
43
|
+
// every reply, not just a document's: the challenge is what points a client here
|
|
44
|
+
input.pipelines.response.push((response) => {
|
|
45
|
+
if (response.status !== UNAUTHORIZED)
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
response.headers ??= new Headers()
|
|
49
|
+
response.headers.set('www-authenticate', known.challenge(input.url.pathname))
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const body = known.read(input.url.pathname)
|
|
53
|
+
|
|
54
|
+
if (body === undefined)
|
|
55
|
+
return null
|
|
56
|
+
|
|
57
|
+
return { body, headers: new Headers({ 'cache-control': 'public, max-age=3600' }) }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The absolute URL an authority is reached at. Loopback is served over http and everything
|
|
63
|
+
* else over https: the gateway may sit behind a terminating proxy, so the connection does
|
|
64
|
+
* not say which, and the configured host does. Taken from the configuration rather than
|
|
65
|
+
* from the request's `host`, which is the client's to write.
|
|
66
|
+
*/
|
|
67
|
+
function origin (host: string): string {
|
|
68
|
+
const name = host.split(':')[0]
|
|
69
|
+
|
|
70
|
+
const loopback = name === 'localhost' || name === '127.0.0.1' || name === '[::1]' ||
|
|
71
|
+
name.endsWith('.localhost')
|
|
72
|
+
|
|
73
|
+
return `${loopback ? 'http' : 'https'}://${host}`
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const UNAUTHORIZED = 401
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { OAuth } from '../../Annotation.js'
|
|
2
|
+
|
|
3
|
+
/** The discovery documents of one authority, and the challenge that points at them. */
|
|
4
|
+
export interface Documents {
|
|
5
|
+
/** The document a path names, or nothing when it names none. */
|
|
6
|
+
read: (pathname: string) => object | undefined
|
|
7
|
+
|
|
8
|
+
/** `WWW-Authenticate` for a request to this path, which names the resource it failed at. */
|
|
9
|
+
challenge: (pathname: string) => string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function documents (issuer: string, oauth: OAuth): Documents {
|
|
13
|
+
const server = authorizationServer(issuer, oauth)
|
|
14
|
+
const resources = protectedResources(issuer, oauth)
|
|
15
|
+
const scope = oauth.scopes === undefined ? '' : `, scope="${oauth.scopes.join(' ')}"`
|
|
16
|
+
|
|
17
|
+
function read (pathname: string): object | undefined {
|
|
18
|
+
if (pathname === AUTHORIZATION_SERVER || pathname === OPENID_CONFIGURATION)
|
|
19
|
+
return server
|
|
20
|
+
|
|
21
|
+
if (pathname.startsWith(PROTECTED_RESOURCE))
|
|
22
|
+
return resources.get(pathname.slice(PROTECTED_RESOURCE.length))
|
|
23
|
+
|
|
24
|
+
return undefined
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function challenge (pathname: string): string {
|
|
28
|
+
return `Bearer resource_metadata="${issuer}${PROTECTED_RESOURCE}${suffix(oauth, pathname)}"${scope}`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { read, challenge }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* RFC 8414. `authorization_endpoint` is the application's own page and may be anywhere;
|
|
36
|
+
* everything else this extension serves. Both flags are load-bearing for a client that
|
|
37
|
+
* prefers Client ID Metadata Documents: without either it falls back to registration.
|
|
38
|
+
*/
|
|
39
|
+
function authorizationServer (issuer: string, oauth: OAuth): object {
|
|
40
|
+
const metadata: Record<string, unknown> = {
|
|
41
|
+
issuer,
|
|
42
|
+
authorization_endpoint: oauth.authorize,
|
|
43
|
+
token_endpoint: `${issuer}${TOKEN}`,
|
|
44
|
+
response_types_supported: ['code'],
|
|
45
|
+
grant_types_supported: ['authorization_code'],
|
|
46
|
+
code_challenge_methods_supported: ['S256'],
|
|
47
|
+
token_endpoint_auth_methods_supported: ['none'],
|
|
48
|
+
client_id_metadata_document_supported: true,
|
|
49
|
+
authorization_response_iss_parameter_supported: true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (oauth.registration === 'open')
|
|
53
|
+
metadata.registration_endpoint = `${issuer}${REGISTRATION}`
|
|
54
|
+
|
|
55
|
+
if (oauth.scopes !== undefined)
|
|
56
|
+
metadata.scopes_supported = oauth.scopes
|
|
57
|
+
|
|
58
|
+
return metadata
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* RFC 9728, keyed by the path the well-known segment is followed by: a client resolving
|
|
63
|
+
* `https://host/mcp` reads `/.well-known/oauth-protected-resource/mcp`, and one that names
|
|
64
|
+
* no path reads the document at the origin.
|
|
65
|
+
*/
|
|
66
|
+
function protectedResources (issuer: string, oauth: OAuth): Map<string, object> {
|
|
67
|
+
const map = new Map<string, object>()
|
|
68
|
+
|
|
69
|
+
for (const path of oauth.resources ?? [])
|
|
70
|
+
map.set(canonical(path), resource(issuer, canonical(path), oauth))
|
|
71
|
+
|
|
72
|
+
map.set('', resource(issuer, '', oauth))
|
|
73
|
+
|
|
74
|
+
return map
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function resource (issuer: string, path: string, oauth: OAuth): object {
|
|
78
|
+
const metadata: Record<string, unknown> = {
|
|
79
|
+
resource: issuer + path,
|
|
80
|
+
authorization_servers: [issuer],
|
|
81
|
+
bearer_methods_supported: ['header']
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (oauth.scopes !== undefined)
|
|
85
|
+
metadata.scopes_supported = oauth.scopes
|
|
86
|
+
|
|
87
|
+
return metadata
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** The document a request to this path was refused against: the longest resource holding it. */
|
|
91
|
+
function suffix (oauth: OAuth, pathname: string): string {
|
|
92
|
+
let longest = ''
|
|
93
|
+
|
|
94
|
+
for (const path of oauth.resources ?? [])
|
|
95
|
+
if (pathname.startsWith(path) && path.length > longest.length)
|
|
96
|
+
longest = path
|
|
97
|
+
|
|
98
|
+
return canonical(longest)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A resource is identified without its trailing slash — the form MCP asks for — while a
|
|
103
|
+
* route is declared with one, so `/mcp/` identifies `…/mcp`.
|
|
104
|
+
*/
|
|
105
|
+
function canonical (path: string): string {
|
|
106
|
+
return path.endsWith('/') ? path.slice(0, -1) : path
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const AUTHORIZATION_SERVER = '/.well-known/oauth-authorization-server'
|
|
110
|
+
const PROTECTED_RESOURCE = '/.well-known/oauth-protected-resource'
|
|
111
|
+
const OPENID_CONFIGURATION = '/.well-known/openid-configuration'
|
|
112
|
+
const TOKEN = '/identity/grants/'
|
|
113
|
+
const REGISTRATION = '/identity/clients/'
|
|
@@ -5,7 +5,7 @@ import { Workflow } from './workflows/index.js'
|
|
|
5
5
|
import { Directive } from './Directive.js'
|
|
6
6
|
import type { Parameter } from '../../RTD/index.js'
|
|
7
7
|
import type { Unit, Location } from './workflows/index.js'
|
|
8
|
-
import type { Maybe } from '@toa.io/
|
|
8
|
+
import type { Maybe } from '@toa.io/core'
|
|
9
9
|
import type { Component } from '@toa.io/core'
|
|
10
10
|
import type { Output } from '../../io.js'
|
|
11
11
|
import type { Input } from './types.js'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Forbidden, NotFound } from '../../HTTP/index.js'
|
|
2
2
|
import * as schemas from './schemas.js'
|
|
3
3
|
import { Directive } from './Directive.js'
|
|
4
|
-
import type { Maybe } from '@toa.io/
|
|
4
|
+
import type { Maybe } from '@toa.io/core'
|
|
5
5
|
import type { Entry, Stream } from '@toa.io/extensions.storages'
|
|
6
6
|
import type { Component } from '@toa.io/core'
|
|
7
7
|
import type { Output } from '../../io.js'
|
|
@@ -7,7 +7,7 @@ import type { Input } from './types.js'
|
|
|
7
7
|
import type { Component } from '@toa.io/core'
|
|
8
8
|
import type { Output } from '../../io.js'
|
|
9
9
|
import type { Remotes } from '../../Remotes.js'
|
|
10
|
-
import type { Maybe } from '@toa.io/
|
|
10
|
+
import type { Maybe } from '@toa.io/core'
|
|
11
11
|
import type { Entry } from '@toa.io/extensions.storages'
|
|
12
12
|
import type { Parameter } from '../../RTD/index.js'
|
|
13
13
|
|
|
@@ -3,7 +3,7 @@ import { console } from 'openspan'
|
|
|
3
3
|
import type { Unit } from './Workflow.js'
|
|
4
4
|
import type { Remotes } from '../../../Remotes.js'
|
|
5
5
|
import type { Component } from '@toa.io/core'
|
|
6
|
-
import type { Maybe } from '@toa.io/
|
|
6
|
+
import type { Maybe } from '@toa.io/core'
|
|
7
7
|
import type { Entry } from '@toa.io/extensions.storages'
|
|
8
8
|
|
|
9
9
|
export class Execution extends Readable {
|
package/source/index.ts
CHANGED
|
@@ -4,3 +4,9 @@ export { components } from './Composition.js'
|
|
|
4
4
|
export { Factory } from './Factory.js'
|
|
5
5
|
|
|
6
6
|
export type { Remotes } from './Remotes.js'
|
|
7
|
+
|
|
8
|
+
// what an operation is written against, rather than the gateway's own
|
|
9
|
+
export type { Claims, Identity } from './userland.js'
|
|
10
|
+
|
|
11
|
+
// what an octets workflow is given
|
|
12
|
+
export type * as octets from './octets.js'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface WorkflowInput<
|
|
2
|
+
TParameters extends Record<string, string> = Record<string, string>,
|
|
3
|
+
TSteps extends Record<string, unknown> = Record<string, unknown>,
|
|
4
|
+
> {
|
|
5
|
+
authority: string
|
|
6
|
+
identity?: string
|
|
7
|
+
storage: string
|
|
8
|
+
path: string
|
|
9
|
+
entry: {
|
|
10
|
+
id: string
|
|
11
|
+
type: string
|
|
12
|
+
size: number
|
|
13
|
+
meta: Record<string, unknown>
|
|
14
|
+
}
|
|
15
|
+
parameters: TParameters
|
|
16
|
+
steps: TSteps
|
|
17
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What Exposition puts into an operation's input, for the operation to be written against.
|
|
3
|
+
*
|
|
4
|
+
* The gateway's own types are its business; these are the application's.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The identity behind the call, as `auth:delegate` embeds it:
|
|
9
|
+
*
|
|
10
|
+
* ```yaml
|
|
11
|
+
* /echo:
|
|
12
|
+
* GET:
|
|
13
|
+
* auth:assert: true
|
|
14
|
+
* auth:delegate: identity
|
|
15
|
+
* endpoint: echo
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* ```javascript
|
|
19
|
+
* export async function computation ({ identity }, context) { }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export interface Identity {
|
|
23
|
+
readonly id: string
|
|
24
|
+
|
|
25
|
+
/** What the identity holds. Delegation resolves them, so they are always here. */
|
|
26
|
+
roles: string[]
|
|
27
|
+
|
|
28
|
+
permissions?: Record<string, string[]>
|
|
29
|
+
|
|
30
|
+
/** How the identity was authenticated; `null` for a transient one. */
|
|
31
|
+
scheme: string | null
|
|
32
|
+
|
|
33
|
+
/** Whether the credentials presented are due to be exchanged. */
|
|
34
|
+
refresh: boolean
|
|
35
|
+
|
|
36
|
+
/** The token's claims, where the identity was federated. */
|
|
37
|
+
claims?: Claims
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A federated token's payload: what it must carry, and whatever else the issuer put there. */
|
|
41
|
+
export interface Claims {
|
|
42
|
+
iss: string
|
|
43
|
+
sub: string
|
|
44
|
+
aud?: string | string[]
|
|
45
|
+
|
|
46
|
+
[claim: string]: unknown
|
|
47
|
+
}
|
|
@@ -19,8 +19,25 @@ export interface Annotation {
|
|
|
19
19
|
ip?: string;
|
|
20
20
|
/** Failed authentications an address may make; none are metered unless set. See `identity.md`. */
|
|
21
21
|
bouncer?: Bouncer;
|
|
22
|
+
/** The authorization server this context exposes; none is exposed without it. */
|
|
23
|
+
oauth?: OAuth;
|
|
22
24
|
'/'?: object;
|
|
23
25
|
}
|
|
26
|
+
export interface OAuth {
|
|
27
|
+
/**
|
|
28
|
+
* Where a client sends the user to consent. The one endpoint of the flow that needs a
|
|
29
|
+
* person, and so the one this extension does not serve: an application builds it.
|
|
30
|
+
*/
|
|
31
|
+
authorize: string;
|
|
32
|
+
/** Paths a token may be restricted to, each advertised as a protected resource. */
|
|
33
|
+
resources?: string[];
|
|
34
|
+
/** What a client may ask for. Each is a role, or a scope within one. */
|
|
35
|
+
scopes?: string[];
|
|
36
|
+
/** Origins whose Client ID Metadata Documents may be read. None are without it. */
|
|
37
|
+
trust?: string[];
|
|
38
|
+
/** Dynamic Client Registration, off unless opened. */
|
|
39
|
+
registration?: 'open' | 'closed';
|
|
40
|
+
}
|
|
24
41
|
export interface Bouncer {
|
|
25
42
|
/** what an address may fail at once, 20 by default */
|
|
26
43
|
attempts?: number;
|
package/transpiled/Factory.js
CHANGED
|
@@ -41,7 +41,7 @@ export class Factory {
|
|
|
41
41
|
const node = root.resolve();
|
|
42
42
|
const methods = new EndpointsFactory(remotes);
|
|
43
43
|
const directives = new DirectivesFactory(families, remotes, this.host, options);
|
|
44
|
-
const interception = new Interception(interceptors);
|
|
44
|
+
const interception = new Interception(interceptors, options);
|
|
45
45
|
const tree = new Tree(node, methods, directives);
|
|
46
46
|
const composition = new Composition(this.host);
|
|
47
47
|
const gateway = new Gateway(broadcast, tree, interception);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAsC,MAAM,UAAU,CAAA;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAA;AAMvC,MAAM,OAAO,OAAO;IACD,IAAI,CAAM;IAE3B,YAAoB,IAAU;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,KAAK,CAAC,MAAM,CAAE,OAAgB,EAAE,IAAiB;QACtD,MAAM,SAAS,GAAc,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;QAC3E,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE5E,4EAA4E;QAC5E,MAAM,MAAM,GAA8B;YACxC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,SAAS,EAAE,OAAO,CAAC,IAAI;YACvB,QAAQ,EAAE,OAAO,CAAC,SAAS,KAAK,UAAU;YAC1C,IAAI;YACJ,OAAO,EAAE,IAAI;SACd,CAAA;QAED,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;IACtC,CAAC;IAEM,KAAK,CAAC,OAAO;QAClB,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAC7C,wCAAwC,CAAC,CAAA;QAE3C,aAAa,EAAE,CAAA;QAEf,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAiB,CAAA;QACjF,MAAM,SAAS,GAAc,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;QACjD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;QAC3B,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAA;QAC7C,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC/E,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,YAAY,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,11 @@ import { Connector } from '@toa.io/core';
|
|
|
2
2
|
import { type OutgoingMessage } from './messages.js';
|
|
3
3
|
import { Context } from './Context.js';
|
|
4
4
|
import type { Protocol } from './types.js';
|
|
5
|
-
import type { Bouncer } from '../Annotation.js';
|
|
5
|
+
import type { Bouncer, OAuth } from '../Annotation.js';
|
|
6
6
|
export declare class Server extends Connector {
|
|
7
7
|
private readonly server;
|
|
8
8
|
private readonly properties;
|
|
9
|
+
/** Host to authority. A map: a `Host` of `constructor` names what a plain object answers. */
|
|
9
10
|
private readonly authorities;
|
|
10
11
|
/** Tracked for the drain: `Http2Server` has no `closeIdleConnections`. */
|
|
11
12
|
private readonly sessions;
|
|
@@ -40,6 +41,8 @@ interface Properties {
|
|
|
40
41
|
ip?: string;
|
|
41
42
|
/** Failed authentications an address may make; none are metered unless set. */
|
|
42
43
|
bouncer?: Bouncer;
|
|
44
|
+
/** The authorization server this context exposes; none is exposed without it. */
|
|
45
|
+
oauth?: OAuth;
|
|
43
46
|
}
|
|
44
47
|
export type Options = {
|
|
45
48
|
authorities: Properties['authorities'];
|