@toa.io/extensions.exposition 1.0.0-alpha.292 → 1.0.0-alpha.293
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/components/identity.basic/package.json +8 -0
- package/components/identity.federation/package.json +8 -0
- package/components/identity.passkeys/package.json +8 -0
- package/components/identity.tokens/package.json +10 -0
- package/package.json +24 -13
- package/transpiled/Endpoint.js +3 -0
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Introspection.d.ts +6 -0
- package/transpiled/Introspection.js +1 -0
- package/transpiled/Introspection.js.map +1 -1
- package/transpiled/MCP/schema.js +2 -2
- package/transpiled/Query.d.ts +2 -12
- package/transpiled/Query.js +2 -12
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RTD/Endpoint.d.ts +2 -3
- package/ui/dist/_app/immutable/assets/0.Cu0AnR_8.css +2 -0
- package/ui/dist/_app/immutable/assets/2.BghF56l_.css +1 -0
- package/ui/dist/_app/immutable/assets/ui.C8aD6zzF.css +1 -0
- package/ui/dist/_app/immutable/chunks/B8GvXrmq.js +1 -0
- package/ui/dist/_app/immutable/chunks/BVDJTrf4.js +3 -0
- package/ui/dist/_app/immutable/chunks/D6q28_Ok.js +86 -0
- package/ui/dist/_app/immutable/chunks/{aLpTDmOc.js → DVlaUfVU.js} +1 -1
- package/ui/dist/_app/immutable/chunks/DpB73ZB6.js +6 -0
- package/ui/dist/_app/immutable/entry/app.CTava8yn.js +2 -0
- package/ui/dist/_app/immutable/entry/start.yWN0gSLA.js +1 -0
- package/ui/dist/_app/immutable/nodes/0.HKRDBYrC.js +1 -0
- package/ui/dist/_app/immutable/nodes/1.CLa0ydOi.js +1 -0
- package/ui/dist/_app/immutable/nodes/2.C9Kaym8C.js +8 -0
- package/ui/dist/_app/immutable/nodes/3.C1X4_rXZ.js +1 -0
- package/ui/dist/_app/immutable/nodes/4.DdzDIi9E.js +1 -0
- package/ui/dist/_app/immutable/nodes/5.DpbmCMdw.js +1 -0
- package/ui/dist/_app/version.json +1 -1
- package/ui/dist/index.html +12 -12
- package/CHANGELOG.md +0 -42
- package/components/identity.bans/tsconfig.tsbuildinfo +0 -1
- package/components/identity.basic/source/lib/credentials.test.ts +0 -18
- package/components/identity.basic/tsconfig.tsbuildinfo +0 -1
- package/components/identity.clients/source/lib/canonical.test.ts +0 -43
- package/components/identity.clients/source/lib/cimd.test.ts +0 -122
- package/components/identity.clients/source/lib/redirect.test.ts +0 -47
- package/components/identity.clients/tsconfig.tsbuildinfo +0 -1
- package/components/identity.credentials/source/list.test.ts +0 -70
- package/components/identity.credentials/tsconfig.tsbuildinfo +0 -1
- package/components/identity.federation/source/lib/discovery.test.ts +0 -60
- package/components/identity.federation/source/list.test.ts +0 -41
- package/components/identity.federation/tsconfig.tsbuildinfo +0 -1
- package/components/identity.grants/tsconfig.tsbuildinfo +0 -1
- package/components/identity.keys/tsconfig.tsbuildinfo +0 -1
- package/components/identity.otp/tsconfig.tsbuildinfo +0 -1
- package/components/identity.passkeys/source/errors.test.ts +0 -34
- package/components/identity.passkeys/source/webauthn.test.ts +0 -26
- package/components/identity.passkeys/tsconfig.tsbuildinfo +0 -1
- package/components/identity.roles/tsconfig.tsbuildinfo +0 -1
- package/components/identity.tokens/source/authenticate.test.ts +0 -112
- package/components/identity.tokens/source/decrypt.test.ts +0 -216
- package/components/identity.tokens/source/encrypt.test.ts +0 -150
- package/components/identity.tokens/source/issue.test.ts +0 -73
- package/components/identity.tokens/source/lib/form.test.ts +0 -25
- package/components/identity.tokens/source/lib/paseto.test.ts +0 -62
- package/components/identity.tokens/tsconfig.tsbuildinfo +0 -1
- package/context.toa.yaml +0 -31
- package/cucumber.mjs +0 -7
- package/documentation/.assets/ia3-dark.jpg +0 -0
- package/documentation/.assets/ia3-light.jpg +0 -0
- package/documentation/.assets/overview-dark.jpg +0 -0
- package/documentation/.assets/overview-light.jpg +0 -0
- package/documentation/.assets/role-scopes-dark.jpg +0 -0
- package/documentation/.assets/role-scopes-light.jpg +0 -0
- package/documentation/.assets/rtd-dark.jpg +0 -0
- package/documentation/.assets/rtd-light.jpg +0 -0
- package/documentation/access.md +0 -350
- package/documentation/authorities.md +0 -51
- package/documentation/cache.md +0 -72
- package/documentation/components.md +0 -472
- package/documentation/consent.md +0 -101
- package/documentation/credentials.md +0 -88
- package/documentation/dev.md +0 -30
- package/documentation/discovery.md +0 -81
- package/documentation/flow.md +0 -44
- package/documentation/help.md +0 -122
- package/documentation/identity.md +0 -304
- package/documentation/introspection.md +0 -123
- package/documentation/io.md +0 -167
- package/documentation/ip.md +0 -24
- package/documentation/map.md +0 -123
- package/documentation/mcp.md +0 -183
- package/documentation/notes/desync.jpg +0 -0
- package/documentation/notes/peers.md +0 -59
- package/documentation/notes/sse.md +0 -71
- package/documentation/notes/throttling.md +0 -122
- package/documentation/oauth.md +0 -180
- package/documentation/octets.md +0 -334
- package/documentation/passkeys.md +0 -11
- package/documentation/protocol.md +0 -120
- package/documentation/query.md +0 -324
- package/documentation/require.md +0 -15
- package/documentation/rpc.md +0 -154
- package/documentation/tracing.md +0 -70
- package/documentation/tree.md +0 -199
- package/features/access.feature +0 -596
- package/features/annotation.feature +0 -32
- package/features/auth.assert.feature +0 -55
- package/features/auth.bearer.feature +0 -120
- package/features/auth.claims.feature +0 -171
- package/features/auth.incept.feature +0 -166
- package/features/auth.input.feature +0 -59
- package/features/authorities.basic.feature +0 -141
- package/features/authorities.feature +0 -71
- package/features/authorities.federation.feature +0 -100
- package/features/authorities.tokens.feature +0 -117
- package/features/body.feature +0 -76
- package/features/cache.feature +0 -368
- package/features/configuration.feature +0 -206
- package/features/cors.feature +0 -127
- package/features/credentials.feature +0 -106
- package/features/debug.feature +0 -34
- package/features/dev.feature +0 -90
- package/features/directives.feature +0 -61
- package/features/discovery.feature +0 -213
- package/features/discovery.ui.feature +0 -213
- package/features/dynamic.feature +0 -192
- package/features/errors.feature +0 -258
- package/features/etag.feature +0 -239
- package/features/flow.feature +0 -148
- package/features/help.feature +0 -512
- package/features/identity.bans.feature +0 -200
- package/features/identity.basic.feature +0 -666
- package/features/identity.feature +0 -240
- package/features/identity.federation.feature +0 -396
- package/features/identity.otp.feature +0 -142
- package/features/identity.roles.feature +0 -568
- package/features/identity.tokens.custom.feature +0 -430
- package/features/identity.tokens.feature +0 -131
- package/features/interruptions.feature +0 -20
- package/features/introspection.feature +0 -565
- package/features/introspection.map.feature +0 -108
- package/features/io.feature +0 -204
- package/features/io.throttle.feature +0 -166
- package/features/map.feature +0 -360
- package/features/mcp.feature +0 -753
- package/features/methods.feature +0 -48
- package/features/oauth.clients.feature +0 -195
- package/features/oauth.discovery.feature +0 -164
- package/features/oauth.grants.feature +0 -301
- package/features/octets.cloudinary.feature +0 -233
- package/features/octets.download.feature +0 -194
- package/features/octets.entries.feature +0 -83
- package/features/octets.feature +0 -306
- package/features/octets.head.feature +0 -40
- package/features/octets.location.feature +0 -83
- package/features/octets.meta.feature +0 -117
- package/features/octets.workflows.feature +0 -565
- package/features/passkeys.feature +0 -66
- package/features/probes.feature +0 -18
- package/features/query.feature +0 -389
- package/features/realtime.feature +0 -34
- package/features/require.feature +0 -66
- package/features/response.feature +0 -103
- package/features/routes.feature +0 -224
- package/features/rpc.feature +0 -429
- package/features/server.feature +0 -21
- package/features/site/_app/immutable/asset.js +0 -1
- package/features/site/favicon.ico +0 -0
- package/features/site/index.html +0 -10
- package/features/steps/.env.example +0 -5
- package/features/steps/Captures.ts +0 -20
- package/features/steps/Cloudinary.ts +0 -12
- package/features/steps/Common.ts +0 -38
- package/features/steps/Components.ts +0 -115
- package/features/steps/Database.ts +0 -106
- package/features/steps/Gateway.ts +0 -239
- package/features/steps/HTTP.ts +0 -96
- package/features/steps/IDP.ts +0 -361
- package/features/steps/Identity.ts +0 -54
- package/features/steps/OTP.ts +0 -42
- package/features/steps/Parameters.ts +0 -162
- package/features/steps/Probe.ts +0 -38
- package/features/steps/Realtime.ts +0 -175
- package/features/steps/Workspace.ts +0 -48
- package/features/steps/components/audit/manifest.toa.yaml +0 -20
- package/features/steps/components/audit/operations/record.js +0 -5
- package/features/steps/components/echo/manifest.toa.yaml +0 -59
- package/features/steps/components/echo/operations/affect.js +0 -3
- package/features/steps/components/echo/operations/compute.js +0 -3
- package/features/steps/components/echo/operations/echo.js +0 -3
- package/features/steps/components/echo/operations/error.js +0 -7
- package/features/steps/components/echo/operations/identity.js +0 -3
- package/features/steps/components/echo/operations/parameters.js +0 -3
- package/features/steps/components/echo/operations/ping.js +0 -3
- package/features/steps/components/echo/operations/unwrap.js +0 -3
- package/features/steps/components/echo.beacon/manifest.toa.yaml +0 -2
- package/features/steps/components/echo.beacon/operations/hello.js +0 -3
- package/features/steps/components/greeter/manifest.toa.yaml +0 -5
- package/features/steps/components/greeter/operations/greet.js +0 -3
- package/features/steps/components/notify/manifest.toa.yaml +0 -20
- package/features/steps/components/notify/operations/send.js +0 -5
- package/features/steps/components/octets.tester/manifest.toa.yaml +0 -73
- package/features/steps/components/octets.tester/operations/authority.js +0 -3
- package/features/steps/components/octets.tester/operations/bar.js +0 -9
- package/features/steps/components/octets.tester/operations/baz.js +0 -9
- package/features/steps/components/octets.tester/operations/concat.js +0 -5
- package/features/steps/components/octets.tester/operations/echo.js +0 -5
- package/features/steps/components/octets.tester/operations/err.js +0 -14
- package/features/steps/components/octets.tester/operations/foo.js +0 -5
- package/features/steps/components/octets.tester/operations/id.js +0 -5
- package/features/steps/components/octets.tester/operations/identity.js +0 -5
- package/features/steps/components/octets.tester/operations/lenna.png +0 -0
- package/features/steps/components/octets.tester/operations/redirect.js +0 -17
- package/features/steps/components/octets.tester/operations/yex.js +0 -14
- package/features/steps/components/octets.tester/operations/yield.js +0 -11
- package/features/steps/components/orders/manifest.toa.yaml +0 -30
- package/features/steps/components/orders/operations/create.js +0 -7
- package/features/steps/components/pots/manifest.toa.yaml +0 -91
- package/features/steps/components/pots/migrations/0002-indexes.yaml +0 -4
- package/features/steps/components/pricing/manifest.toa.yaml +0 -13
- package/features/steps/components/pricing/operations/quote.js +0 -3
- package/features/steps/components/sequences/manifest.toa.yaml +0 -11
- package/features/steps/components/sequences/operations/numbers.js +0 -5
- package/features/steps/components/sequences/operations/tokens.js +0 -14
- package/features/steps/components/users/manifest.toa.yaml +0 -30
- package/features/steps/components/users/operations/create.js +0 -11
- package/features/steps/components/users.properties/manifest.toa.yaml +0 -22
- package/features/steps/map.ts +0 -30
- package/features/steps/tsconfig.json +0 -9
- package/features/streams.feature +0 -35
- package/features/timestamps.feature +0 -41
- package/features/timing.feature +0 -49
- package/features/tracing.feature +0 -123
- package/source/Branch.test.ts +0 -40
- package/source/Branch.ts +0 -44
- package/source/Composition.ts +0 -51
- package/source/Context.ts +0 -11
- package/source/Directive.test.ts +0 -199
- package/source/Directive.ts +0 -248
- package/source/Discovery/Explorer.ts +0 -34
- package/source/Discovery/Site.test.ts +0 -147
- package/source/Discovery/Site.ts +0 -202
- package/source/Discovery/index.ts +0 -3
- package/source/Discovery/tree.test.ts +0 -175
- package/source/Discovery/tree.ts +0 -77
- package/source/Discovery/trunk.ts +0 -33
- package/source/Endpoint.test.ts +0 -67
- package/source/Endpoint.ts +0 -157
- package/source/Factory.ts +0 -42
- package/source/Gateway.ts +0 -390
- package/source/HTTP/Context.ts +0 -143
- package/source/HTTP/Probe.ts +0 -99
- package/source/HTTP/Server.ts +0 -435
- package/source/HTTP/Timing.ts +0 -14
- package/source/HTTP/address.test.ts +0 -28
- package/source/HTTP/address.ts +0 -16
- package/source/HTTP/exceptions.ts +0 -99
- package/source/HTTP/formats/form.ts +0 -21
- package/source/HTTP/formats/index.ts +0 -36
- package/source/HTTP/formats/json.ts +0 -14
- package/source/HTTP/formats/msgpack.ts +0 -14
- package/source/HTTP/formats/text.ts +0 -10
- package/source/HTTP/formats/yaml.test.ts +0 -22
- package/source/HTTP/formats/yaml.ts +0 -40
- package/source/HTTP/index.ts +0 -6
- package/source/HTTP/messages.test.ts +0 -196
- package/source/HTTP/messages.ts +0 -186
- package/source/HTTP/types.ts +0 -39
- package/source/Interception.ts +0 -37
- package/source/Introspection.ts +0 -179
- package/source/MCP/Server.ts +0 -335
- package/source/MCP/discover.ts +0 -51
- package/source/MCP/errors.ts +0 -80
- package/source/MCP/index.ts +0 -1
- package/source/MCP/schema.test.ts +0 -91
- package/source/MCP/schema.ts +0 -94
- package/source/MCP/tools.ts +0 -144
- package/source/MCP/types.ts +0 -84
- package/source/Mapping.ts +0 -101
- package/source/Query.test.ts +0 -54
- package/source/Query.ts +0 -277
- package/source/RPC/Context.ts +0 -75
- package/source/RPC/Dispatcher.ts +0 -150
- package/source/RPC/errors.test.ts +0 -77
- package/source/RPC/errors.ts +0 -82
- package/source/RPC/index.ts +0 -1
- package/source/RPC/names.test.ts +0 -141
- package/source/RPC/names.ts +0 -176
- package/source/RPC/types.ts +0 -34
- package/source/RTD/Context.ts +0 -16
- package/source/RTD/Directives.ts +0 -126
- package/source/RTD/Endpoint.ts +0 -27
- package/source/RTD/Match.ts +0 -11
- package/source/RTD/Method.ts +0 -39
- package/source/RTD/Node.ts +0 -169
- package/source/RTD/Route.ts +0 -93
- package/source/RTD/Tree.ts +0 -137
- package/source/RTD/expiration.test.ts +0 -81
- package/source/RTD/factory.ts +0 -105
- package/source/RTD/index.ts +0 -8
- package/source/RTD/segment.test.ts +0 -35
- package/source/RTD/segment.ts +0 -51
- package/source/RTD/syntax/index.ts +0 -1
- package/source/RTD/walk.test.ts +0 -147
- package/source/Remotes.test.ts +0 -79
- package/source/Remotes.ts +0 -39
- package/source/Tenant.ts +0 -73
- package/source/directives/auth/Anonymous.test.ts +0 -70
- package/source/directives/auth/Anonymous.ts +0 -36
- package/source/directives/auth/Anyone.ts +0 -23
- package/source/directives/auth/Assert.ts +0 -43
- package/source/directives/auth/Authorization.test.ts +0 -24
- package/source/directives/auth/Authorization.ts +0 -388
- package/source/directives/auth/Delegate.test.ts +0 -36
- package/source/directives/auth/Delegate.ts +0 -54
- package/source/directives/auth/Echo.ts +0 -24
- package/source/directives/auth/Federation.ts +0 -104
- package/source/directives/auth/Id.ts +0 -37
- package/source/directives/auth/Incept.ts +0 -117
- package/source/directives/auth/Input.ts +0 -92
- package/source/directives/auth/Role.test.ts +0 -147
- package/source/directives/auth/Role.ts +0 -99
- package/source/directives/auth/Rule.ts +0 -59
- package/source/directives/auth/Scheme.ts +0 -31
- package/source/directives/auth/create.ts +0 -11
- package/source/directives/auth/index.ts +0 -3
- package/source/directives/auth/schemes.test.ts +0 -18
- package/source/directives/auth/schemes.ts +0 -39
- package/source/directives/auth/split.ts +0 -14
- package/source/directives/auth/types.ts +0 -75
- package/source/directives/cache/Cache.ts +0 -92
- package/source/directives/cache/Control.ts +0 -81
- package/source/directives/cache/Exact.ts +0 -7
- package/source/directives/cache/etag.ts +0 -38
- package/source/directives/cache/index.ts +0 -3
- package/source/directives/cache/types.ts +0 -9
- package/source/directives/cors/CORS.test.ts +0 -75
- package/source/directives/cors/CORS.ts +0 -88
- package/source/directives/cors/index.ts +0 -3
- package/source/directives/dev/Development.ts +0 -41
- package/source/directives/dev/Faulty.ts +0 -31
- package/source/directives/dev/Sleep.ts +0 -53
- package/source/directives/dev/Stub.ts +0 -14
- package/source/directives/dev/Throw.ts +0 -14
- package/source/directives/dev/index.ts +0 -3
- package/source/directives/dev/types.ts +0 -5
- package/source/directives/flow/Compose.ts +0 -98
- package/source/directives/flow/Fetch.ts +0 -86
- package/source/directives/flow/Flow.ts +0 -43
- package/source/directives/flow/index.ts +0 -3
- package/source/directives/flow/types.ts +0 -7
- package/source/directives/help/Family.ts +0 -122
- package/source/directives/help/Help.test.ts +0 -227
- package/source/directives/help/Help.ts +0 -47
- package/source/directives/help/Parameters.ts +0 -47
- package/source/directives/help/described.ts +0 -57
- package/source/directives/help/index.ts +0 -45
- package/source/directives/index.ts +0 -33
- package/source/directives/io/Directive.ts +0 -17
- package/source/directives/io/IO.ts +0 -118
- package/source/directives/io/Input.ts +0 -55
- package/source/directives/io/Message.ts +0 -1
- package/source/directives/io/Output.ts +0 -81
- package/source/directives/io/Status.test.ts +0 -88
- package/source/directives/io/Status.ts +0 -47
- package/source/directives/io/Throttle.ts +0 -30
- package/source/directives/io/index.ts +0 -3
- package/source/directives/io/lib/throttle/Configuration.test.ts +0 -72
- package/source/directives/io/lib/throttle/Configuration.ts +0 -68
- package/source/directives/io/lib/throttle/Keys.ts +0 -53
- package/source/directives/io/lib/throttle/Quotas.test.ts +0 -411
- package/source/directives/io/lib/throttle/Quotas.ts +0 -190
- package/source/directives/io/lib/throttle/Sync.test.ts +0 -163
- package/source/directives/io/lib/throttle/Sync.ts +0 -93
- package/source/directives/io/lib/throttle/Warning.test.ts +0 -32
- package/source/directives/io/lib/throttle/Warning.ts +0 -29
- package/source/directives/io/lib/throttle/components/Component.ts +0 -7
- package/source/directives/io/lib/throttle/components/IP.ts +0 -30
- package/source/directives/io/lib/throttle/components/Identity.ts +0 -19
- package/source/directives/io/lib/throttle/components/Path.ts +0 -8
- package/source/directives/io/lib/throttle/components/Route.ts +0 -19
- package/source/directives/io/lib/throttle/components/Segment.ts +0 -19
- package/source/directives/io/lib/throttle/components/index.ts +0 -19
- package/source/directives/io/lib/throttle/conditions/Condition.ts +0 -5
- package/source/directives/io/lib/throttle/conditions/Status.ts +0 -17
- package/source/directives/io/lib/throttle/conditions/index.ts +0 -11
- package/source/directives/io/lib/throttle/index.ts +0 -4
- package/source/directives/io/schemas.test.ts +0 -40
- package/source/directives/io/schemas.ts +0 -16
- package/source/directives/map/Authority.ts +0 -15
- package/source/directives/map/Buffer.ts +0 -15
- package/source/directives/map/Claims.ts +0 -63
- package/source/directives/map/Directive.ts +0 -4
- package/source/directives/map/Headers.ts +0 -60
- package/source/directives/map/Language.ts +0 -45
- package/source/directives/map/Languages.ts +0 -17
- package/source/directives/map/Map.ts +0 -85
- package/source/directives/map/Mapping.ts +0 -45
- package/source/directives/map/Properties.ts +0 -15
- package/source/directives/map/Segments.ts +0 -52
- package/source/directives/map/index.ts +0 -3
- package/source/directives/mcp/MCP.ts +0 -33
- package/source/directives/mcp/Tool.test.ts +0 -56
- package/source/directives/mcp/Tool.ts +0 -32
- package/source/directives/mcp/index.ts +0 -6
- package/source/directives/oauth/Discovery.ts +0 -66
- package/source/directives/oauth/documents.ts +0 -110
- package/source/directives/oauth/index.ts +0 -3
- package/source/directives/octets/Context.ts +0 -23
- package/source/directives/octets/Delete.ts +0 -96
- package/source/directives/octets/Directive.ts +0 -21
- package/source/directives/octets/Get.ts +0 -88
- package/source/directives/octets/Octets.ts +0 -82
- package/source/directives/octets/Put.ts +0 -186
- package/source/directives/octets/Workflow.ts +0 -60
- package/source/directives/octets/bytes.test.ts +0 -33
- package/source/directives/octets/bytes.ts +0 -18
- package/source/directives/octets/index.ts +0 -3
- package/source/directives/octets/schemas.test.ts +0 -20
- package/source/directives/octets/schemas.ts +0 -15
- package/source/directives/octets/types.ts +0 -9
- package/source/directives/octets/workflows/Execution.ts +0 -130
- package/source/directives/octets/workflows/Workflow.ts +0 -51
- package/source/directives/octets/workflows/index.ts +0 -1
- package/source/directives/require/Directive.ts +0 -5
- package/source/directives/require/Headers.ts +0 -19
- package/source/directives/require/Require.ts +0 -27
- package/source/directives/require/index.ts +0 -3
- package/source/discovery.ts +0 -1
- package/source/exceptions.ts +0 -47
- package/source/index.ts +0 -10
- package/source/io.ts +0 -4
- package/source/octets.d.ts +0 -17
- package/source/root.ts +0 -59
- package/source/service.ts +0 -95
- package/source/userland.ts +0 -47
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- package/ui/dist/_app/immutable/assets/0.Bl7vLmIK.css +0 -2
- package/ui/dist/_app/immutable/assets/2.BC0-Jhqu.css +0 -1
- package/ui/dist/_app/immutable/chunks/BaWe3aOV.js +0 -1
- package/ui/dist/_app/immutable/chunks/DjIYL2zC.js +0 -3
- package/ui/dist/_app/immutable/chunks/GZTfV0ks.js +0 -6
- package/ui/dist/_app/immutable/entry/app.D5v4JoUx.js +0 -2
- package/ui/dist/_app/immutable/entry/start.CWxFoIyZ.js +0 -1
- package/ui/dist/_app/immutable/nodes/0.DIh5T_5-.js +0 -1
- package/ui/dist/_app/immutable/nodes/1.CY-bFzHC.js +0 -1
- package/ui/dist/_app/immutable/nodes/2.6Ubd1ItY.js +0 -14
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { cors } from '../cors/index.js'
|
|
3
|
-
import { Mapping } from './Mapping.js'
|
|
4
|
-
import { take } from '../../Introspection.js'
|
|
5
|
-
import type { Input } from '../../io.js'
|
|
6
|
-
import type { Introspection } from '../../Introspection.js'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Forbidden request header names: the browser sets them itself and a script cannot
|
|
10
|
-
* list them in `Access-Control-Request-Headers`, so there is nothing to advertise
|
|
11
|
-
* or vary on. The value is still read, it just never reaches CORS.
|
|
12
|
-
*/
|
|
13
|
-
const FORBIDDEN = new Set(['host', 'origin'])
|
|
14
|
-
|
|
15
|
-
export class Headers extends Mapping<Record<string, string>> {
|
|
16
|
-
private readonly headers: string[]
|
|
17
|
-
|
|
18
|
-
public constructor(map: Record<string, string>) {
|
|
19
|
-
assert.ok(map.constructor === Object, '`map:headers` must be an object')
|
|
20
|
-
|
|
21
|
-
assert.ok(
|
|
22
|
-
Object.values(map).every((value) => typeof value === 'string'),
|
|
23
|
-
'`map:headers` must be an object with string values'
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
super(map)
|
|
27
|
-
|
|
28
|
-
this.headers = Object.values(map).filter((header) => !FORBIDDEN.has(header))
|
|
29
|
-
this.headers.forEach((header) => cors.allow(header))
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The property is filled from a request header, so it is not the body's to send. Which
|
|
34
|
-
* header, and that there is one at all, is not answered: what an application reads off a
|
|
35
|
-
* request is its own, and a caller has nowhere to put one anyway.
|
|
36
|
-
*/
|
|
37
|
-
public override explain(introspection: Introspection): void {
|
|
38
|
-
for (const property of Object.keys(this.value)) take(introspection, property)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public properties(context: Input): Record<string, string> {
|
|
42
|
-
context.pipelines.response.push((response) => {
|
|
43
|
-
response.headers ??= new global.Headers()
|
|
44
|
-
|
|
45
|
-
for (const header of this.headers) response.headers.append('vary', header)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
return Object.entries(this.value).reduce(
|
|
49
|
-
(properties: Record<string, string>, [property, header]) => {
|
|
50
|
-
const value = context.request.headers[header]
|
|
51
|
-
|
|
52
|
-
if (value !== undefined)
|
|
53
|
-
properties[property] = Array.isArray(value) ? value.join(', ') : value
|
|
54
|
-
|
|
55
|
-
return properties
|
|
56
|
-
},
|
|
57
|
-
{}
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import Negotiator from 'negotiator'
|
|
3
|
-
import { cors } from '../cors/index.js'
|
|
4
|
-
import { Mapping } from './Mapping.js'
|
|
5
|
-
import { Languages } from './Languages.js'
|
|
6
|
-
import type { Input } from '../../io.js'
|
|
7
|
-
import type { Parameter } from '../../RTD/index.js'
|
|
8
|
-
import type { Directive } from './Directive.js'
|
|
9
|
-
|
|
10
|
-
export class Language extends Mapping<string> {
|
|
11
|
-
private languages: string[] | null = null
|
|
12
|
-
|
|
13
|
-
public constructor(property: string) {
|
|
14
|
-
assert.ok(typeof property === 'string', '`map:language` must be a string')
|
|
15
|
-
|
|
16
|
-
cors.allow('accept-language')
|
|
17
|
-
super(property)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public properties(
|
|
21
|
-
context: Input,
|
|
22
|
-
parameters: Parameter[],
|
|
23
|
-
directives: Directive[]
|
|
24
|
-
): Record<string, string> {
|
|
25
|
-
this.languages ??= this.resolve(directives)
|
|
26
|
-
|
|
27
|
-
const negotiator = new Negotiator(context.request)
|
|
28
|
-
const language = negotiator.language(this.languages) ?? this.languages[0]
|
|
29
|
-
|
|
30
|
-
context.pipelines.response.push((response) => {
|
|
31
|
-
response.headers ??= new Headers()
|
|
32
|
-
response.headers.set('content-language', language)
|
|
33
|
-
response.headers.append('vary', 'accept-language')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
return { [this.value]: language }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
private resolve(directives: Directive[]): string[] {
|
|
40
|
-
for (const directive of directives)
|
|
41
|
-
if (directive instanceof Languages) return directive.value
|
|
42
|
-
|
|
43
|
-
throw new Error('Supported languages are not defined, add `map:languages` directive')
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Property } from './Properties.js'
|
|
3
|
-
|
|
4
|
-
export class Languages extends Property<'languages'> {
|
|
5
|
-
public constructor(value: string[]) {
|
|
6
|
-
assert.ok(
|
|
7
|
-
Array.isArray(value) && value.length > 0,
|
|
8
|
-
'`map:languages` must be a non-empty array of strings'
|
|
9
|
-
)
|
|
10
|
-
assert.ok(
|
|
11
|
-
value.every((language) => typeof language === 'string'),
|
|
12
|
-
'`map:languages` must be an array of strings'
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
super('languages', value)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { match } from 'matchacho'
|
|
2
|
-
import { properties, Property } from './Properties.js'
|
|
3
|
-
import { Mapping } from './Mapping.js'
|
|
4
|
-
import { Headers } from './Headers.js'
|
|
5
|
-
import { Languages } from './Languages.js'
|
|
6
|
-
import { Language } from './Language.js'
|
|
7
|
-
import { Segments } from './Segments.js'
|
|
8
|
-
import { Authority } from './Authority.js'
|
|
9
|
-
import { BufferMapping } from './Buffer.js'
|
|
10
|
-
import { Claims } from './Claims.js'
|
|
11
|
-
import type { Directive } from './Directive.js'
|
|
12
|
-
import type { Properties } from './Properties.js'
|
|
13
|
-
import type { DirectiveFamily, Parameter } from '../../RTD/index.js'
|
|
14
|
-
import type { Input, Output } from '../../io.js'
|
|
15
|
-
import type { Introspection } from '../../Introspection.js'
|
|
16
|
-
import type { Remotes } from '../../Remotes.js'
|
|
17
|
-
|
|
18
|
-
export class Map implements DirectiveFamily {
|
|
19
|
-
public readonly name = 'map'
|
|
20
|
-
public readonly mandatory = false
|
|
21
|
-
|
|
22
|
-
private remotes!: Remotes
|
|
23
|
-
|
|
24
|
-
public create(name: string, value: unknown, remotes: Remotes): Property | Mapping {
|
|
25
|
-
this.remotes = remotes
|
|
26
|
-
|
|
27
|
-
return match(
|
|
28
|
-
name,
|
|
29
|
-
() => properties.has(name),
|
|
30
|
-
(name: PN) => new Property(name, value as PV),
|
|
31
|
-
() => name in mappings,
|
|
32
|
-
(name: keyof typeof mappings) => new mappings[name](value, remotes),
|
|
33
|
-
() => {
|
|
34
|
-
throw new Error(`Directive 'map:${name}' is not implemented`)
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public explain(
|
|
40
|
-
directives: Directive[],
|
|
41
|
-
_: Input,
|
|
42
|
-
introspection: Introspection
|
|
43
|
-
): Introspection {
|
|
44
|
-
for (const directive of directives)
|
|
45
|
-
if (directive instanceof Mapping) directive.explain(introspection)
|
|
46
|
-
|
|
47
|
-
return introspection
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
public async precall(
|
|
51
|
-
directives: Directive[],
|
|
52
|
-
context: Input,
|
|
53
|
-
parameters: Parameter[]
|
|
54
|
-
): Promise<Output> {
|
|
55
|
-
const properties = {}
|
|
56
|
-
|
|
57
|
-
for (const directive of directives)
|
|
58
|
-
if (directive instanceof Mapping)
|
|
59
|
-
Object.assign(
|
|
60
|
-
properties,
|
|
61
|
-
await directive.properties(context, parameters, directives)
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
context.pipelines.body.push((body: unknown) => {
|
|
65
|
-
if (body === undefined || body === null || typeof body !== 'object')
|
|
66
|
-
return properties
|
|
67
|
-
else return Object.assign(body, properties)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
return null
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
type PN = keyof Properties
|
|
75
|
-
type PV = Properties[PN]
|
|
76
|
-
|
|
77
|
-
const mappings: Record<string, new (value: any, remotes: Remotes) => Directive> = {
|
|
78
|
-
authority: Authority,
|
|
79
|
-
buffer: BufferMapping,
|
|
80
|
-
headers: Headers,
|
|
81
|
-
languages: Languages,
|
|
82
|
-
language: Language,
|
|
83
|
-
segments: Segments,
|
|
84
|
-
claims: Claims
|
|
85
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { take } from '../../Introspection.js'
|
|
2
|
-
import type { Remotes } from '../../Remotes.js'
|
|
3
|
-
import type { Directive } from './Directive.js'
|
|
4
|
-
import type { Input } from '../../io.js'
|
|
5
|
-
import type { Parameter } from '../../RTD/index.js'
|
|
6
|
-
import type { Introspection } from '../../Introspection.js'
|
|
7
|
-
|
|
8
|
-
export abstract class Mapping<T = unknown> {
|
|
9
|
-
protected value: T
|
|
10
|
-
protected remotes?: Remotes
|
|
11
|
-
|
|
12
|
-
protected constructor(value: T, remotes?: Remotes) {
|
|
13
|
-
this.value = value
|
|
14
|
-
this.remotes = remotes
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public abstract properties(
|
|
18
|
-
context: Input,
|
|
19
|
-
parameters: Parameter[],
|
|
20
|
-
directives: Directive[]
|
|
21
|
-
): Output
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* What this mapping does to what the method says about itself, which is the reverse of
|
|
25
|
-
* what it does to a request: a property the gateway fills is taken out of the input,
|
|
26
|
-
* because it is not the caller's to send.
|
|
27
|
-
*
|
|
28
|
-
* The default says nothing more than that. A claim, an authority and a language come
|
|
29
|
-
* from the request itself and there is nowhere for a caller to put one; a header and a
|
|
30
|
-
* segment are the caller's, and those say where.
|
|
31
|
-
*/
|
|
32
|
-
public explain(introspection: Introspection): void {
|
|
33
|
-
for (const property of this.names()) take(introspection, property)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** The input properties this mapping fills, however its value names them. */
|
|
37
|
-
protected names(): string[] {
|
|
38
|
-
return typeof this.value === 'string'
|
|
39
|
-
? [this.value]
|
|
40
|
-
: Object.keys(this.value as object)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
type Properties = Record<string, unknown> | null
|
|
45
|
-
type Output = Properties | Promise<Properties>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface Properties {
|
|
2
|
-
languages: string[]
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export class Property<K extends keyof Properties = keyof Properties> {
|
|
6
|
-
public readonly name: K
|
|
7
|
-
public readonly value: Properties[K]
|
|
8
|
-
|
|
9
|
-
public constructor(name: K, value: Properties[K]) {
|
|
10
|
-
this.name = name
|
|
11
|
-
this.value = value
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const properties = new Set('languages')
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Mapping } from './Mapping.js'
|
|
3
|
-
import { take } from '../../Introspection.js'
|
|
4
|
-
import type { Parameter } from '../../RTD/index.js'
|
|
5
|
-
import type { Introspection, Schema } from '../../Introspection.js'
|
|
6
|
-
|
|
7
|
-
export class Segments extends Mapping<Record<string, string>> {
|
|
8
|
-
public constructor(map: Record<string, string>) {
|
|
9
|
-
assert.ok(map.constructor === Object, '`map:segments` must be an object')
|
|
10
|
-
|
|
11
|
-
assert.ok(
|
|
12
|
-
Object.values(map).every((value) => typeof value === 'string'),
|
|
13
|
-
'`map:segments ` must be an object with string values'
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
super(map)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** A segment is the caller's, so it moves to the route rather than out of sight. */
|
|
20
|
-
public override explain(introspection: Introspection): void {
|
|
21
|
-
for (const property of Object.keys(this.value)) {
|
|
22
|
-
const schema = take(introspection, property)
|
|
23
|
-
|
|
24
|
-
introspection.route ??= {}
|
|
25
|
-
introspection.route[property] = schema ?? ({ type: 'string' } as unknown as Schema)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public override properties(
|
|
30
|
-
_: unknown,
|
|
31
|
-
parameters: Parameter[]
|
|
32
|
-
): Record<string, string> {
|
|
33
|
-
return Object.entries(this.value).reduce(
|
|
34
|
-
(properties: Record<string, string>, [property, parameter]) => {
|
|
35
|
-
const cut = parameter[0] === '~'
|
|
36
|
-
|
|
37
|
-
if (cut) parameter = parameter.slice(1)
|
|
38
|
-
|
|
39
|
-
const index = parameters.findIndex(({ name }) => name === parameter)
|
|
40
|
-
|
|
41
|
-
assert.ok(index > -1, `Route parameter '${parameter}' is missing`)
|
|
42
|
-
|
|
43
|
-
properties[property] = parameters[index].value
|
|
44
|
-
|
|
45
|
-
if (cut) parameters.splice(index, 1)
|
|
46
|
-
|
|
47
|
-
return properties
|
|
48
|
-
},
|
|
49
|
-
{}
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Tool } from './Tool.js'
|
|
3
|
-
import type { DirectiveFamily } from '../../RTD/index.js'
|
|
4
|
-
import type { Context } from '../../HTTP/index.js'
|
|
5
|
-
import type { Introspection } from '../../Introspection.js'
|
|
6
|
-
|
|
7
|
-
/** The name the family is declared under, and what `MCP` asks a method for. */
|
|
8
|
-
export const FAMILY = 'mcp'
|
|
9
|
-
|
|
10
|
-
export class MCP implements DirectiveFamily<Tool> {
|
|
11
|
-
public readonly name = FAMILY
|
|
12
|
-
public readonly mandatory = false
|
|
13
|
-
|
|
14
|
-
/** Whether this method is published, which is what the nearest declaration says. */
|
|
15
|
-
public static published(directives: Tool[] | undefined): boolean {
|
|
16
|
-
return directives?.[0]?.published ?? false
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Whether this method is published to a model, which is what the route declares. Whether
|
|
21
|
-
* one is served at all is the annotation's, and a route says nothing of that.
|
|
22
|
-
*/
|
|
23
|
-
public explain(directives: Tool[], _: Context, introspection: Introspection): Introspection {
|
|
24
|
-
return MCP.published(directives) ? { ...introspection, mcp: true } : introspection
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// eslint-disable-next-line max-params
|
|
28
|
-
public create(name: string, value: unknown, _: unknown, route: string): Tool {
|
|
29
|
-
assert.ok(name === 'tool', `Unknown directive: mcp:${name}`)
|
|
30
|
-
|
|
31
|
-
return new Tool(value, route)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { describe, it } from 'node:test'
|
|
3
|
-
import { Tool } from './Tool.js'
|
|
4
|
-
import { MCP } from './MCP.js'
|
|
5
|
-
|
|
6
|
-
describe('mcp:tool', () => {
|
|
7
|
-
it('should publish a method', () => {
|
|
8
|
-
assert.strictEqual(new Tool(true, '/pots/hot').published, true)
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('should withdraw one, because a declaration is inherited', () => {
|
|
12
|
-
assert.strictEqual(new Tool(false, '/pots/hot').published, false)
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('should not accept what a tool is, which is `help:method`', () => {
|
|
16
|
-
assert.throws(() => new Tool('The pots that are hot.', '/pots'), /`help:method`/)
|
|
17
|
-
assert.throws(() => new Tool({ title: 'Hot pots' }, '/pots'), /`help:method`/)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('should not accept a value that is not one', () => {
|
|
21
|
-
assert.throws(() => new Tool(undefined, '/pots'), /whether the method is published/)
|
|
22
|
-
assert.throws(() => new Tool(null, '/pots'), /whether the method is published/)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('should refuse a route no name can spell', () => {
|
|
26
|
-
assert.throws(() => new Tool(true, '/pots/v1.0'), /no tool name can spell/)
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('should name the route it refuses', () => {
|
|
30
|
-
assert.throws(() => new Tool(true, '/pots/v1.0'), /'\/pots\/v1\.0'/)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should not ask a route it does not publish to be spellable', () => {
|
|
34
|
-
assert.strictEqual(new Tool(false, '/pots/v1.0').published, false)
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
describe('mcp:tool inheritance', () => {
|
|
39
|
-
const mcp = new MCP()
|
|
40
|
-
|
|
41
|
-
it('should take the nearest declaration', () => {
|
|
42
|
-
const nearest = new Tool(false, '/pots')
|
|
43
|
-
const further = new Tool(true, '/pots')
|
|
44
|
-
|
|
45
|
-
assert.strictEqual(MCP.published([nearest, further]), false)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('should publish nothing where nothing is declared', () => {
|
|
49
|
-
assert.strictEqual(MCP.published(undefined), false)
|
|
50
|
-
assert.strictEqual(MCP.published([]), false)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('should refuse a directive it does not know', () => {
|
|
54
|
-
assert.throws(() => mcp.create('tools', true, null, '/pots'), /Unknown directive/)
|
|
55
|
-
})
|
|
56
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { refusal } from '../../RPC/names.js'
|
|
3
|
-
import { segment } from '../../RTD/segment.js'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Whether one method is published to a model. Declaring it is what publishes it, and it
|
|
7
|
-
* says nothing else — what a tool is, is [`help:method`](../help/Help.ts), which is what
|
|
8
|
-
* describes the method to everything else as well.
|
|
9
|
-
*
|
|
10
|
-
* `false` withdraws one: the declaration is inherited, as every directive is, and a node
|
|
11
|
-
* publishing what is under it is how a subtree is published at all.
|
|
12
|
-
*/
|
|
13
|
-
export class Tool {
|
|
14
|
-
public readonly published: boolean
|
|
15
|
-
|
|
16
|
-
public constructor(value: unknown, route: string) {
|
|
17
|
-
assert.ok(
|
|
18
|
-
typeof value === 'boolean',
|
|
19
|
-
'Directive mcp:tool: the value is whether the method is published; what it is, is `help:method`'
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
// a tool is called by name, so a route that cannot be named cannot be one — said where
|
|
23
|
-
// the mistake is, rather than as a tool that is quietly never listed
|
|
24
|
-
if (value)
|
|
25
|
-
assert.ok(
|
|
26
|
-
refusal(segment(route)) === null,
|
|
27
|
-
`Directive mcp:tool: '${route}' holds a segment no tool name can spell`
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
this.published = value
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
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) return
|
|
27
|
-
|
|
28
|
-
/*
|
|
29
|
-
* `https` always: RFC 8414 has an issuer be one, and OAuth 2.1 has every endpoint of an
|
|
30
|
-
* authorization server be one — the loopback exception is a client's redirect URI, not
|
|
31
|
-
* a server's address. A gateway served without TLS has no authorization server a client
|
|
32
|
-
* may use, and naming it `http` would hide that behind documents none should accept.
|
|
33
|
-
*
|
|
34
|
-
* The host is the configured one, not the request's, which is the client's to write: a
|
|
35
|
-
* forged one would have these documents name someone else's token endpoint.
|
|
36
|
-
*/
|
|
37
|
-
for (const [authority, host] of Object.entries(options.authorities))
|
|
38
|
-
this.authorities.set(authority, documents(`https://${host}`, options.oauth))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public reset(): void {
|
|
42
|
-
this.authorities.clear()
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public intercept(input: Input): Output {
|
|
46
|
-
const known = this.authorities.get(input.authority)
|
|
47
|
-
|
|
48
|
-
if (known === undefined) return null
|
|
49
|
-
|
|
50
|
-
// every reply, not just a document's: the challenge is what points a client here
|
|
51
|
-
input.pipelines.response.push((response) => {
|
|
52
|
-
if (response.status !== UNAUTHORIZED) return
|
|
53
|
-
|
|
54
|
-
response.headers ??= new Headers()
|
|
55
|
-
response.headers.set('www-authenticate', known.challenge(input.url.pathname))
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
const body = known.read(input.url.pathname)
|
|
59
|
-
|
|
60
|
-
if (body === undefined) return null
|
|
61
|
-
|
|
62
|
-
return { body, headers: new Headers({ 'cache-control': 'public, max-age=3600' }) }
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const UNAUTHORIZED = 401
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import type { OAuth } from '@toa.io/definitions/extensions.exposition'
|
|
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) metadata.scopes_supported = oauth.scopes
|
|
56
|
-
|
|
57
|
-
return metadata
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* RFC 9728, keyed by the path the well-known segment is followed by: a client resolving
|
|
62
|
-
* `https://host/mcp` reads `/.well-known/oauth-protected-resource/mcp`, and one that names
|
|
63
|
-
* no path reads the document at the origin.
|
|
64
|
-
*/
|
|
65
|
-
function protectedResources(issuer: string, oauth: OAuth): Map<string, object> {
|
|
66
|
-
const map = new Map<string, object>()
|
|
67
|
-
|
|
68
|
-
for (const path of oauth.resources ?? [])
|
|
69
|
-
map.set(canonical(path), resource(issuer, canonical(path), oauth))
|
|
70
|
-
|
|
71
|
-
map.set('', resource(issuer, '', oauth))
|
|
72
|
-
|
|
73
|
-
return map
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function resource(issuer: string, path: string, oauth: OAuth): object {
|
|
77
|
-
const metadata: Record<string, unknown> = {
|
|
78
|
-
resource: issuer + path,
|
|
79
|
-
authorization_servers: [issuer],
|
|
80
|
-
bearer_methods_supported: ['header']
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (oauth.scopes !== undefined) metadata.scopes_supported = oauth.scopes
|
|
84
|
-
|
|
85
|
-
return metadata
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** The document a request to this path was refused against: the longest resource holding it. */
|
|
89
|
-
function suffix(oauth: OAuth, pathname: string): string {
|
|
90
|
-
let longest = ''
|
|
91
|
-
|
|
92
|
-
for (const path of oauth.resources ?? [])
|
|
93
|
-
if (pathname.startsWith(path) && path.length > longest.length) longest = path
|
|
94
|
-
|
|
95
|
-
return canonical(longest)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* A resource is identified without its trailing slash — the form MCP asks for — while a
|
|
100
|
-
* route is declared with one, so `/mcp/` identifies `…/mcp`.
|
|
101
|
-
*/
|
|
102
|
-
function canonical(path: string): string {
|
|
103
|
-
return path.endsWith('/') ? path.slice(0, -1) : path
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const AUTHORIZATION_SERVER = '/.well-known/oauth-authorization-server'
|
|
107
|
-
const PROTECTED_RESOURCE = '/.well-known/oauth-protected-resource'
|
|
108
|
-
const OPENID_CONFIGURATION = '/.well-known/openid-configuration'
|
|
109
|
-
const TOKEN = '/identity/grants/'
|
|
110
|
-
const REGISTRATION = '/identity/clients/'
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { Directive } from './Directive.js'
|
|
3
|
-
import type { Output } from '../../io.js'
|
|
4
|
-
|
|
5
|
-
export class Context extends Directive {
|
|
6
|
-
public readonly targeted = false
|
|
7
|
-
public readonly storage: string
|
|
8
|
-
|
|
9
|
-
public constructor(value: unknown) {
|
|
10
|
-
super()
|
|
11
|
-
|
|
12
|
-
assert.ok(
|
|
13
|
-
typeof value === 'string',
|
|
14
|
-
"Directive 'octets:context' must must be a string"
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
this.storage = value
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
public async apply(): Promise<Output> {
|
|
21
|
-
return null
|
|
22
|
-
}
|
|
23
|
-
}
|