@toa.io/extensions.exposition 1.0.0-alpha.291 → 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 +25 -13
- package/transpiled/Discovery/Explorer.js +1 -1
- package/transpiled/Discovery/Explorer.js.map +1 -1
- package/transpiled/Discovery/Site.js +1 -1
- package/transpiled/Discovery/Site.js.map +1 -1
- package/transpiled/Discovery/trunk.js +1 -1
- package/transpiled/Discovery/trunk.js.map +1 -1
- package/transpiled/Endpoint.js +3 -0
- package/transpiled/Endpoint.js.map +1 -1
- package/transpiled/Factory.js +1 -1
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Gateway.js +1 -1
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +1 -1
- package/transpiled/HTTP/Server.js +1 -1
- package/transpiled/HTTP/Server.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/Server.d.ts +1 -1
- package/transpiled/MCP/Server.js +1 -1
- package/transpiled/MCP/Server.js.map +1 -1
- package/transpiled/MCP/discover.d.ts +1 -1
- package/transpiled/MCP/schema.js +2 -2
- package/transpiled/Query.d.ts +2 -12
- package/transpiled/Query.js +3 -13
- package/transpiled/Query.js.map +1 -1
- package/transpiled/RPC/Dispatcher.d.ts +1 -1
- package/transpiled/RPC/Dispatcher.js +2 -2
- package/transpiled/RPC/Dispatcher.js.map +1 -1
- package/transpiled/RTD/Endpoint.d.ts +2 -3
- package/transpiled/RTD/Tree.js +1 -1
- package/transpiled/RTD/Tree.js.map +1 -1
- package/transpiled/RTD/factory.js +1 -1
- package/transpiled/RTD/factory.js.map +1 -1
- package/transpiled/RTD/syntax/index.d.ts +1 -2
- package/transpiled/RTD/syntax/index.js +1 -2
- package/transpiled/RTD/syntax/index.js.map +1 -1
- package/transpiled/Tenant.js +1 -1
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +1 -1
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/io/IO.js +1 -1
- package/transpiled/directives/io/IO.js.map +1 -1
- package/transpiled/directives/oauth/documents.d.ts +1 -1
- package/transpiled/index.d.ts +0 -2
- package/transpiled/index.js +0 -2
- package/transpiled/index.js.map +1 -1
- package/transpiled/service.js +1 -1
- package/transpiled/service.js.map +1 -1
- 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/{D9tE1yyO.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 -35
- 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 -240
- 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/schemas/annotation.cos.yaml +0 -125
- package/schemas/call.cos.yaml +0 -18
- package/schemas/directive.cos.yaml +0 -7
- package/schemas/method.cos.yaml +0 -23
- package/schemas/node.cos.yaml +0 -22
- package/schemas/query.cos.yaml +0 -31
- package/schemas/querystring.cos.yaml +0 -19
- package/schemas/range.cos.yaml +0 -10
- package/schemas/route.cos.yaml +0 -6
- package/source/Annotation.ts +0 -89
- 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 -430
- 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 -2
- package/source/RTD/syntax/parse.test.ts +0 -196
- package/source/RTD/syntax/parse.ts +0 -171
- package/source/RTD/syntax/types.ts +0 -69
- 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/const.ts +0 -45
- package/source/deployment.ts +0 -96
- 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 -12
- package/source/io.ts +0 -4
- package/source/manifest.test.ts +0 -56
- package/source/manifest.ts +0 -56
- package/source/octets.d.ts +0 -17
- package/source/root.ts +0 -59
- package/source/schemas.test.ts +0 -31
- package/source/schemas.ts +0 -15
- package/source/service.ts +0 -94
- package/source/shortcuts.ts +0 -14
- package/source/userland.ts +0 -47
- package/transpiled/Annotation.d.ts +0 -70
- package/transpiled/Annotation.js +0 -2
- package/transpiled/Annotation.js.map +0 -1
- package/transpiled/RTD/syntax/parse.d.ts +0 -4
- package/transpiled/RTD/syntax/parse.js +0 -112
- package/transpiled/RTD/syntax/parse.js.map +0 -1
- package/transpiled/RTD/syntax/types.d.ts +0 -52
- package/transpiled/RTD/syntax/types.js +0 -11
- package/transpiled/RTD/syntax/types.js.map +0 -1
- package/transpiled/const.d.ts +0 -36
- package/transpiled/const.js +0 -37
- package/transpiled/const.js.map +0 -1
- package/transpiled/deployment.d.ts +0 -6
- package/transpiled/deployment.js +0 -76
- package/transpiled/deployment.js.map +0 -1
- package/transpiled/manifest.d.ts +0 -3
- package/transpiled/manifest.js +0 -39
- package/transpiled/manifest.js.map +0 -1
- package/transpiled/schemas.d.ts +0 -9
- package/transpiled/schemas.js +0 -9
- package/transpiled/schemas.js.map +0 -1
- package/transpiled/shortcuts.d.ts +0 -3
- package/transpiled/shortcuts.js +0 -13
- package/transpiled/shortcuts.js.map +0 -1
- 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/B_pK3U1C.js +0 -6
- package/ui/dist/_app/immutable/chunks/CiKbPLyY.js +0 -1
- package/ui/dist/_app/immutable/chunks/DjIYL2zC.js +0 -3
- package/ui/dist/_app/immutable/entry/app.DMqmL4NY.js +0 -2
- package/ui/dist/_app/immutable/entry/start.CRe7HWBI.js +0 -1
- package/ui/dist/_app/immutable/nodes/0.D9m-6cbM.js +0 -1
- package/ui/dist/_app/immutable/nodes/1.Cgi_RcSO.js +0 -1
- package/ui/dist/_app/immutable/nodes/2.D_Cbxgz4.js +0 -14
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { match } from 'matchacho'
|
|
3
|
-
import { console } from 'openspan'
|
|
4
|
-
import { Minimatch } from 'minimatch'
|
|
5
|
-
import * as http from '../../HTTP/index.js'
|
|
6
|
-
import { Anonymous } from './Anonymous.js'
|
|
7
|
-
import { Id } from './Id.js'
|
|
8
|
-
import { Role } from './Role.js'
|
|
9
|
-
import { Rule } from './Rule.js'
|
|
10
|
-
import { Incept } from './Incept.js'
|
|
11
|
-
import { Assert } from './Assert.js'
|
|
12
|
-
import { Echo } from './Echo.js'
|
|
13
|
-
import { Scheme } from './Scheme.js'
|
|
14
|
-
import { Delegate } from './Delegate.js'
|
|
15
|
-
import { Federation } from './Federation.js'
|
|
16
|
-
import { Anyone } from './Anyone.js'
|
|
17
|
-
import { Input, type Declaration } from './Input.js'
|
|
18
|
-
import { split } from './split.js'
|
|
19
|
-
import { PRIMARY, UNRECOGNIZED, providers as providersOf } from './schemes.js'
|
|
20
|
-
import { ATOM_GROUP } from '../../const.js'
|
|
21
|
-
import { Quotas, Sync } from '../io/lib/throttle/index.js'
|
|
22
|
-
import { Keys } from '../io/lib/throttle/Keys.js'
|
|
23
|
-
import type { Output } from '../../io.js'
|
|
24
|
-
import type { Introspection } from '../../Introspection.js'
|
|
25
|
-
import type { Component } from '@toa.io/core'
|
|
26
|
-
import type { Remotes } from '../../Remotes.js'
|
|
27
|
-
import type { Parameter, DirectiveFamily } from '../../RTD/index.js'
|
|
28
|
-
import type { Host } from '../../Factory.js'
|
|
29
|
-
import type {
|
|
30
|
-
AuthenticationResult,
|
|
31
|
-
Ban,
|
|
32
|
-
Directive,
|
|
33
|
-
Discovery,
|
|
34
|
-
Extension,
|
|
35
|
-
Identity,
|
|
36
|
-
Context,
|
|
37
|
-
Remote,
|
|
38
|
-
Components
|
|
39
|
-
} from './types.js'
|
|
40
|
-
|
|
41
|
-
export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
42
|
-
public readonly depends: string[] = ['Vary']
|
|
43
|
-
public readonly name: string = 'auth'
|
|
44
|
-
public readonly mandatory: boolean = true
|
|
45
|
-
|
|
46
|
-
private readonly components: Components = {}
|
|
47
|
-
private readonly discovery = {} as unknown as Discovery
|
|
48
|
-
private tokens: Component | null = null
|
|
49
|
-
private bans: Component | null = null
|
|
50
|
-
|
|
51
|
-
/** Failed authentications per address, reconciled with the other gateways. */
|
|
52
|
-
private meter: Quotas | null = null
|
|
53
|
-
private sync: Sync | null = null
|
|
54
|
-
|
|
55
|
-
public mount(host: Host, options: http.Options): void {
|
|
56
|
-
this.sync?.dispose()
|
|
57
|
-
this.sync = null
|
|
58
|
-
this.meter = null
|
|
59
|
-
|
|
60
|
-
const bouncer = options.bouncer
|
|
61
|
-
|
|
62
|
-
// keyed by address, which is the deployment's to name, so off until it is set
|
|
63
|
-
if (bouncer === undefined) return
|
|
64
|
-
|
|
65
|
-
this.meter = new Quotas({
|
|
66
|
-
keys: Keys.create([{ method: 'ip', options: BOUNCER }]),
|
|
67
|
-
requests: bouncer.attempts ?? ATTEMPTS,
|
|
68
|
-
interval: (bouncer.interval ?? INTERVAL) * 1000,
|
|
69
|
-
conditional: true, // charged on a rejection, not on a check
|
|
70
|
-
name: METER
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
this.sync = new Sync(host.atom(ATOM_GROUP))
|
|
74
|
-
this.sync.register(this.meter)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
public dispose(): void {
|
|
78
|
-
this.sync?.dispose()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public create(name: string, value: any, remotes: Remotes): Directive {
|
|
82
|
-
assert.ok(name in constructors, `Directive 'auth:${name}' is not implemented`)
|
|
83
|
-
|
|
84
|
-
const Class = constructors[name]
|
|
85
|
-
|
|
86
|
-
for (const name of REMOTES)
|
|
87
|
-
this.discovery[name] ??= remotes.discover('identity', name)
|
|
88
|
-
|
|
89
|
-
return match(
|
|
90
|
-
Class,
|
|
91
|
-
Role,
|
|
92
|
-
() => new Role(value as string | string[], this.discovery.roles),
|
|
93
|
-
Rule,
|
|
94
|
-
() => new Rule(value as Record<string, string>, this.create.bind(this)),
|
|
95
|
-
Input,
|
|
96
|
-
() => new Input(value as Declaration[], this.create.bind(this)),
|
|
97
|
-
Incept,
|
|
98
|
-
() => new Incept(value as string, this.discovery),
|
|
99
|
-
Delegate,
|
|
100
|
-
() => new Delegate(value as string, this.discovery.roles),
|
|
101
|
-
() => new Class(value)
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
public arrange(directives: Directive[]): void {
|
|
106
|
-
directives.sort((a, b) => (a.priority ?? 1) - (b.priority ?? 1))
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Authentication: who the credential names, if one is presented. A credential belongs to
|
|
111
|
-
* the request, so it is read once however many calls the request carries.
|
|
112
|
-
*/
|
|
113
|
-
public async preflight(context: Context): Promise<void> {
|
|
114
|
-
context.identity = await this.resolve(context)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Authorization: whether that identity may make this call, which every call asks anew. */
|
|
118
|
-
public async precall(
|
|
119
|
-
directives: Directive[],
|
|
120
|
-
context: Context,
|
|
121
|
-
parameters: Parameter[]
|
|
122
|
-
): Promise<Output> {
|
|
123
|
-
for (const directive of directives) {
|
|
124
|
-
const allow = await directive.authorize(context.identity, context, parameters)
|
|
125
|
-
|
|
126
|
-
if (allow)
|
|
127
|
-
if (this.permitted(context)) return directive.reply?.(context) ?? null
|
|
128
|
-
else throw new http.Forbidden()
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (context.identity === null) throw new http.Unauthorized()
|
|
132
|
-
else throw new http.Forbidden()
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* The same disjunction as `precall`, over what can be told without a request. A method no
|
|
137
|
-
* directive admits, and none is undecided about, is not this caller's to be told about —
|
|
138
|
-
* `null` takes it out of the answer.
|
|
139
|
-
*
|
|
140
|
-
* A permission is matched against a path, and a description is not a request to one, so
|
|
141
|
-
* `permits` has no say here. The call it describes is still checked, which is where a
|
|
142
|
-
* token's permissions belong.
|
|
143
|
-
*
|
|
144
|
-
* A method that is described is then described by each of them, which is a separate pass:
|
|
145
|
-
* admission is a disjunction and stops at the first that admits, while what the directives
|
|
146
|
-
* fill is not any one of them's to state alone.
|
|
147
|
-
*/
|
|
148
|
-
public async explain(
|
|
149
|
-
directives: Directive[],
|
|
150
|
-
context: Context,
|
|
151
|
-
introspection: Introspection
|
|
152
|
-
): Promise<Introspection | null> {
|
|
153
|
-
let untold = false
|
|
154
|
-
let admitted = false
|
|
155
|
-
|
|
156
|
-
for (const directive of directives) {
|
|
157
|
-
const admits = await directive.admits?.(context.identity, context)
|
|
158
|
-
|
|
159
|
-
if (admits === undefined) {
|
|
160
|
-
untold = true
|
|
161
|
-
|
|
162
|
-
continue
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (admits) {
|
|
166
|
-
admitted = true
|
|
167
|
-
|
|
168
|
-
break
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (!admitted && !untold) return null
|
|
173
|
-
|
|
174
|
-
// whichever of them admitted, a property any of them fills from the identity is filled
|
|
175
|
-
// from the identity: what a caller sent there would be overwritten or forged
|
|
176
|
-
for (const directive of directives)
|
|
177
|
-
introspection = directive.describe?.(introspection) ?? introspection
|
|
178
|
-
|
|
179
|
-
return introspection
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
public async settle(
|
|
183
|
-
directives: Directive[],
|
|
184
|
-
context: Context,
|
|
185
|
-
response: http.OutgoingMessage
|
|
186
|
-
): Promise<void> {
|
|
187
|
-
await Promise.all(
|
|
188
|
-
directives.map(async (directive) => directive.settle?.(context, response))
|
|
189
|
-
)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Re-issuing a credential, and refusing a ban, are the request's business: the header
|
|
194
|
-
* carries one token however many calls were made, and a ban refuses all of them.
|
|
195
|
-
*/
|
|
196
|
-
public async depart(context: Context, response: http.OutgoingMessage): Promise<void> {
|
|
197
|
-
const identity = context.identity
|
|
198
|
-
|
|
199
|
-
if (identity === null) return
|
|
200
|
-
|
|
201
|
-
if (identity.provider === PRIMARY && !identity.refresh) return
|
|
202
|
-
|
|
203
|
-
// resolving already asked, for any provider but the primary
|
|
204
|
-
if (context.vetted !== true && (await this.banned(identity)))
|
|
205
|
-
throw new http.Unauthorized()
|
|
206
|
-
|
|
207
|
-
// a token carries the roles it was issued with, and the refresh is where they are read again;
|
|
208
|
-
// any other scheme has just read them, unless a Role directive already did
|
|
209
|
-
if (identity.provider === PRIMARY)
|
|
210
|
-
identity.roles = await Role.get(identity, this.discovery.roles)
|
|
211
|
-
else identity.roles ??= await Role.get(identity, this.discovery.roles)
|
|
212
|
-
this.tokens ??= await this.discovery.tokens
|
|
213
|
-
|
|
214
|
-
const token = await this.tokens.invoke<string>('encrypt', {
|
|
215
|
-
input: { authority: context.authority, identity }
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
const authorization = `Token ${token}`
|
|
219
|
-
|
|
220
|
-
response.headers ??= new Headers()
|
|
221
|
-
response.headers.set('authorization', authorization)
|
|
222
|
-
response.headers.set('cache-control', 'no-store')
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
private async resolve(context: Context): Promise<Identity | null> {
|
|
226
|
-
const { authority } = context
|
|
227
|
-
const { authorization } = context.request.headers
|
|
228
|
-
|
|
229
|
-
if (authorization === undefined) return null
|
|
230
|
-
|
|
231
|
-
const retry = this.meter?.check(context, NONE) ?? 0
|
|
232
|
-
|
|
233
|
-
if (retry > 0) throw new http.TooManyRequests(retry)
|
|
234
|
-
|
|
235
|
-
const [scheme, credentials] = split(authorization)
|
|
236
|
-
const candidates = providersOf(scheme)
|
|
237
|
-
|
|
238
|
-
if (candidates === undefined)
|
|
239
|
-
throw new http.Unauthorized(`Unknown authentication scheme '${scheme}'`)
|
|
240
|
-
|
|
241
|
-
let provider: Remote | null = null
|
|
242
|
-
let result: AuthenticationResult | null = null
|
|
243
|
-
|
|
244
|
-
// the first provider that does not decline has claimed the credentials, and answers
|
|
245
|
-
// for them: a rejection from one that never recognized them is not the rejection
|
|
246
|
-
for (const candidate of candidates) {
|
|
247
|
-
this.components[candidate] ??= await this.discovery[candidate]
|
|
248
|
-
|
|
249
|
-
const answer = await this.components[candidate]!.invoke<AuthenticationResult>(
|
|
250
|
-
'authenticate',
|
|
251
|
-
{
|
|
252
|
-
input: {
|
|
253
|
-
scheme,
|
|
254
|
-
authority,
|
|
255
|
-
credentials
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
if (declined(answer)) continue
|
|
261
|
-
|
|
262
|
-
provider = candidate
|
|
263
|
-
result = answer
|
|
264
|
-
|
|
265
|
-
break
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (result === null || result instanceof Error) {
|
|
269
|
-
const code = result === null ? UNRECOGNIZED : codeOf(result)
|
|
270
|
-
|
|
271
|
-
if (code !== undefined) {
|
|
272
|
-
console.info('Authentication failed', { code })
|
|
273
|
-
|
|
274
|
-
context.rejection = code
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
this.meter?.use(context, null)
|
|
278
|
-
|
|
279
|
-
return null
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const identity = result.identity
|
|
283
|
-
|
|
284
|
-
if (provider !== PRIMARY) {
|
|
285
|
-
if (await this.banned(identity)) throw new http.Unauthorized()
|
|
286
|
-
|
|
287
|
-
context.vetted = true
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
identity.scheme = scheme
|
|
291
|
-
identity.provider = provider!
|
|
292
|
-
identity.refresh = result.refresh
|
|
293
|
-
|
|
294
|
-
return identity
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
private permitted(context: Context): boolean {
|
|
298
|
-
const permissions = context.identity?.permissions
|
|
299
|
-
|
|
300
|
-
if (permissions === undefined) return true
|
|
301
|
-
|
|
302
|
-
// the route is matched on the normalized path, so the permission is too
|
|
303
|
-
return permits(permissions, context.request.method, context.url.pathname)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
private async banned(identity: Identity): Promise<boolean> {
|
|
307
|
-
this.bans ??= await this.discovery.bans
|
|
308
|
-
|
|
309
|
-
const ban = await this.bans.invoke<Ban>('observe', { query: { id: identity.id } })
|
|
310
|
-
|
|
311
|
-
return ban.banned
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/** Whether a provider says the credentials are not of its kind, so the next is asked. */
|
|
316
|
-
function declined(result: AuthenticationResult): boolean {
|
|
317
|
-
return result instanceof Error && codeOf(result) === UNRECOGNIZED
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function codeOf(result: Error): string | undefined {
|
|
321
|
-
const code: string | unknown = (result as unknown as { code: string }).code
|
|
322
|
-
|
|
323
|
-
return typeof code === 'string' ? code : undefined
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/** Whether the permissions admit the method on the path the request is routed by. */
|
|
327
|
-
export function permits(
|
|
328
|
-
permissions: Record<string, string[]>,
|
|
329
|
-
method: string,
|
|
330
|
-
pathname: string
|
|
331
|
-
): boolean {
|
|
332
|
-
return Object.entries(permissions).some(
|
|
333
|
-
([pattern, methods]) =>
|
|
334
|
-
methods.some((allowed) => allowed === '*' || allowed === method) &&
|
|
335
|
-
glob(pattern).match(pathname)
|
|
336
|
-
)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* `minimatch(str, pattern)` compiles the pattern on every call, and a permission is
|
|
341
|
-
* matched on every request the identity makes. Patterns arrive with an identity, hence
|
|
342
|
-
* the bound.
|
|
343
|
-
*/
|
|
344
|
-
function glob(pattern: string): Minimatch {
|
|
345
|
-
let compiled = GLOBS.get(pattern)
|
|
346
|
-
|
|
347
|
-
if (compiled === undefined) {
|
|
348
|
-
if (GLOBS.size >= GLOBS_LIMIT) GLOBS.clear()
|
|
349
|
-
|
|
350
|
-
compiled = new Minimatch(pattern)
|
|
351
|
-
|
|
352
|
-
GLOBS.set(pattern, compiled)
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
return compiled
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/** What an address may fail at once, and the seconds it takes to earn them back. */
|
|
359
|
-
const ATTEMPTS = 20
|
|
360
|
-
const INTERVAL = 60
|
|
361
|
-
|
|
362
|
-
/** Who is speaking when a request cannot be keyed. */
|
|
363
|
-
const BOUNCER = 'Authentication bouncer'
|
|
364
|
-
|
|
365
|
-
/** The meter's name in the atom: `atom:exposition:meter:credentials:<address>`. */
|
|
366
|
-
const METER = 'credentials'
|
|
367
|
-
|
|
368
|
-
const NONE: Parameter[] = []
|
|
369
|
-
|
|
370
|
-
const GLOBS = new Map<string, Minimatch>()
|
|
371
|
-
const GLOBS_LIMIT = 1024
|
|
372
|
-
|
|
373
|
-
const constructors: Record<string, new (value: any, argument?: any) => Directive> = {
|
|
374
|
-
anonymous: Anonymous,
|
|
375
|
-
anyone: Anyone,
|
|
376
|
-
id: Id,
|
|
377
|
-
role: Role,
|
|
378
|
-
rule: Rule,
|
|
379
|
-
incept: Incept,
|
|
380
|
-
assert: Assert,
|
|
381
|
-
scheme: Scheme,
|
|
382
|
-
echo: Echo,
|
|
383
|
-
delegate: Delegate,
|
|
384
|
-
claims: Federation,
|
|
385
|
-
input: Input
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const REMOTES: Remote[] = ['basic', 'federation', 'tokens', 'roles', 'bans', 'otp']
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import { describe, it } from 'node:test'
|
|
3
|
-
import { Delegate } from './Delegate.js'
|
|
4
|
-
import type { Introspection } from '../../Introspection.js'
|
|
5
|
-
|
|
6
|
-
describe('auth:delegate', () => {
|
|
7
|
-
function explanation(): Introspection {
|
|
8
|
-
return {
|
|
9
|
-
input: {
|
|
10
|
-
type: 'object',
|
|
11
|
-
properties: {
|
|
12
|
-
identity: { type: 'object' },
|
|
13
|
-
title: { type: 'string' }
|
|
14
|
-
},
|
|
15
|
-
required: ['identity', 'title']
|
|
16
|
-
}
|
|
17
|
-
} as unknown as Introspection
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
it('should take the property it embeds out of the input', () => {
|
|
21
|
-
const delegate = new Delegate('identity', null as never)
|
|
22
|
-
const described = delegate.describe(explanation())
|
|
23
|
-
const input = described.input as { properties: object; required: string[] }
|
|
24
|
-
|
|
25
|
-
assert.deepStrictEqual(Object.keys(input.properties), ['title'])
|
|
26
|
-
assert.deepStrictEqual(input.required, ['title'])
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('should leave an input that does not declare it alone', () => {
|
|
30
|
-
const delegate = new Delegate('originator', null as never)
|
|
31
|
-
const described = delegate.describe(explanation())
|
|
32
|
-
const input = described.input as { properties: object }
|
|
33
|
-
|
|
34
|
-
assert.deepStrictEqual(Object.keys(input.properties), ['identity', 'title'])
|
|
35
|
-
})
|
|
36
|
-
})
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { BadRequest } from '../../HTTP/index.js'
|
|
2
|
-
import { take } from '../../Introspection.js'
|
|
3
|
-
import { Role } from './Role.js'
|
|
4
|
-
import type { Introspection } from '../../Introspection.js'
|
|
5
|
-
import type { Context, Directive, Identity } from './types.js'
|
|
6
|
-
import type { Component } from '@toa.io/core'
|
|
7
|
-
|
|
8
|
-
export class Delegate implements Directive {
|
|
9
|
-
private readonly property: string
|
|
10
|
-
private readonly discovery: Promise<Component>
|
|
11
|
-
|
|
12
|
-
public constructor(property: string, discovery: Promise<Component>) {
|
|
13
|
-
this.property = property
|
|
14
|
-
this.discovery = discovery
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public async authorize(identity: Identity | null, context: Context): Promise<boolean> {
|
|
18
|
-
if (identity === null) return false
|
|
19
|
-
|
|
20
|
-
identity.roles ??= await Role.get(identity, this.discovery)
|
|
21
|
-
context.pipelines.body.push((body) => this.embed(body, identity))
|
|
22
|
-
|
|
23
|
-
return true
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** It admits whoever there is, and embedding the identity is the request's business. */
|
|
27
|
-
public admits(identity: Identity | null): boolean {
|
|
28
|
-
return identity !== null
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* It takes an identity, and the property it embeds is that identity's — so a caller has
|
|
33
|
-
* nothing to put there.
|
|
34
|
-
*/
|
|
35
|
-
public describe(introspection: Introspection): Introspection {
|
|
36
|
-
take(introspection, this.property)
|
|
37
|
-
|
|
38
|
-
return { ...introspection, authenticated: true }
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private embed(body: unknown, identity: Identity): Record<string, unknown> {
|
|
42
|
-
if (body === undefined) body = {}
|
|
43
|
-
|
|
44
|
-
check(body)
|
|
45
|
-
body[this.property] = structuredClone(identity)
|
|
46
|
-
|
|
47
|
-
return body
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function check(body: unknown): asserts body is Record<string, unknown> {
|
|
52
|
-
if (typeof body !== 'object' || body === null)
|
|
53
|
-
throw new BadRequest('Invalid request body')
|
|
54
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { create } from './create.js'
|
|
2
|
-
import type { OutgoingMessage } from '../../HTTP/index.js'
|
|
3
|
-
import type { Directive, Identity, Context } from './types.js'
|
|
4
|
-
|
|
5
|
-
export class Echo implements Directive {
|
|
6
|
-
public authorize(identity: Identity | null, context: Context): boolean {
|
|
7
|
-
if (identity === null && 'authorization' in context.request.headers) return false
|
|
8
|
-
|
|
9
|
-
context.identity ??= create()
|
|
10
|
-
|
|
11
|
-
return true
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** What `authorize` answers, without inventing the identity it would go on to invent. */
|
|
15
|
-
public admits(identity: Identity | null, context: Context): boolean {
|
|
16
|
-
return !(identity === null && 'authorization' in context.request.headers)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public reply(context: Context): OutgoingMessage {
|
|
20
|
-
const body = context.identity!
|
|
21
|
-
|
|
22
|
-
return body.scheme === null ? { status: 201, body } : { body }
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
|
-
import type { Directive, Identity, Context } from './types.js'
|
|
3
|
-
import type { Introspection } from '../../Introspection.js'
|
|
4
|
-
import type { Parameter } from '../../RTD/index.js'
|
|
5
|
-
|
|
6
|
-
export class Federation implements Directive {
|
|
7
|
-
private readonly matchers: Array<[keyof Claims, Matcher]>
|
|
8
|
-
|
|
9
|
-
public constructor(options: Options) {
|
|
10
|
-
this.matchers = (Object.entries(options) as Array<[keyof Claims, string]>).map(
|
|
11
|
-
([key, value]) => [key, toMatcher(value)]
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
assert.ok(
|
|
15
|
-
this.matchers.length > 0,
|
|
16
|
-
'`auth:claims` requires at least one property defined'
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Which claims it takes needs the request; that it takes an identity does not. */
|
|
21
|
-
public admits(identity: Identity | null): boolean | undefined {
|
|
22
|
-
return identity === null ? false : undefined
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Which claims is the application's business; that it takes an identity is the caller's. */
|
|
26
|
-
public describe(introspection: Introspection): Introspection {
|
|
27
|
-
return { ...introspection, authenticated: true }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public authorize(
|
|
31
|
-
identity: Identity | null,
|
|
32
|
-
context: Context,
|
|
33
|
-
parameters: Parameter[]
|
|
34
|
-
): boolean {
|
|
35
|
-
if (identity === null || !('claims' in identity)) return false
|
|
36
|
-
|
|
37
|
-
const claims = (identity as FederatedIdentity).claims
|
|
38
|
-
|
|
39
|
-
for (const [key, match] of this.matchers)
|
|
40
|
-
if (!match(claims[key], context, parameters)) return false
|
|
41
|
-
|
|
42
|
-
return true
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function toMatcher(expression: string): Matcher {
|
|
47
|
-
if (expression.startsWith(':')) {
|
|
48
|
-
const key = expression.slice(1) as 'authority'
|
|
49
|
-
|
|
50
|
-
if (key === 'authority') return (value, context) => matches(value, context[key])
|
|
51
|
-
|
|
52
|
-
if (key === 'domain')
|
|
53
|
-
return (value, context) => {
|
|
54
|
-
return Array.isArray(value)
|
|
55
|
-
? value.some((iss) => codomain(iss, context))
|
|
56
|
-
: codomain(value, context)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
throw new Error('Unknown `auth:claims` syntax: ' + expression)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (expression.startsWith('/:')) {
|
|
63
|
-
const name = expression.slice(2)
|
|
64
|
-
|
|
65
|
-
return (value, _, parameters) =>
|
|
66
|
-
parameters.some(
|
|
67
|
-
(parameter) => parameter.name === name && matches(value, parameter.value)
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return (value) => matches(value, expression)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function matches(value: string | string[], reference: string): boolean {
|
|
75
|
-
return Array.isArray(value) ? value.includes(reference) : value === reference
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function codomain(iss: string, context: Context): boolean {
|
|
79
|
-
const hostname = new URL(iss).hostname
|
|
80
|
-
const dot = hostname.indexOf('.')
|
|
81
|
-
const basename = dot === -1 ? hostname : hostname.slice(dot)
|
|
82
|
-
|
|
83
|
-
return context.authority.slice(-basename.length) === basename
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
type Matcher = (
|
|
87
|
-
value: string | string[],
|
|
88
|
-
context: Context,
|
|
89
|
-
parameters: Parameter[]
|
|
90
|
-
) => boolean
|
|
91
|
-
|
|
92
|
-
interface Claims {
|
|
93
|
-
iss: string
|
|
94
|
-
sub: string
|
|
95
|
-
aud: string | string[]
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
interface Options extends Partial<Claims> {
|
|
99
|
-
iss: string
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
interface FederatedIdentity extends Identity {
|
|
103
|
-
claims: Claims
|
|
104
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { type Parameter } from '../../RTD/index.js'
|
|
2
|
-
import { type Directive, type Identity } from './types.js'
|
|
3
|
-
import type { Introspection } from '../../Introspection.js'
|
|
4
|
-
|
|
5
|
-
export class Id implements Directive {
|
|
6
|
-
private readonly parameter: string
|
|
7
|
-
|
|
8
|
-
public constructor(parameter: string) {
|
|
9
|
-
this.parameter = parameter
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Whether it is *this* identity's cannot be told from a description, which has no route
|
|
14
|
-
* variable to read — but that there must be an identity at all can, and a caller with
|
|
15
|
-
* none is refused whatever the value would have been.
|
|
16
|
-
*/
|
|
17
|
-
public admits(identity: Identity | null): boolean | undefined {
|
|
18
|
-
return identity === null ? false : undefined
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Reaching it is being the identity it is about, which is what `private` says. */
|
|
22
|
-
public describe(introspection: Introspection): Introspection {
|
|
23
|
-
return { ...introspection, private: true }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public authorize(
|
|
27
|
-
identity: Identity | null,
|
|
28
|
-
_: unknown,
|
|
29
|
-
parameters: Parameter[]
|
|
30
|
-
): boolean {
|
|
31
|
-
if (identity === null) return false
|
|
32
|
-
|
|
33
|
-
const parameter = parameters.find((parameter) => parameter.name === this.parameter)
|
|
34
|
-
|
|
35
|
-
return parameter?.value === identity.id
|
|
36
|
-
}
|
|
37
|
-
}
|