@frontmcp/sdk 0.4.0 → 0.5.0
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/README.md +30 -18
- package/package.json +20 -5
- package/src/app/app.registry.d.ts +3 -2
- package/src/app/app.registry.js +3 -1
- package/src/app/app.registry.js.map +1 -1
- package/src/app/instances/app.local.instance.js +2 -2
- package/src/app/instances/app.local.instance.js.map +1 -1
- package/src/auth/auth.registry.d.ts +34 -2
- package/src/auth/auth.registry.js +162 -24
- package/src/auth/auth.registry.js.map +1 -1
- package/src/auth/auth.utils.js +8 -9
- package/src/auth/auth.utils.js.map +1 -1
- package/src/auth/authorization/authorization.class.d.ts +125 -0
- package/src/auth/authorization/authorization.class.js +224 -0
- package/src/auth/authorization/authorization.class.js.map +1 -0
- package/src/auth/authorization/authorization.types.d.ts +300 -0
- package/src/auth/authorization/authorization.types.js +79 -0
- package/src/auth/authorization/authorization.types.js.map +1 -0
- package/src/auth/authorization/index.d.ts +5 -0
- package/src/auth/authorization/index.js +19 -0
- package/src/auth/authorization/index.js.map +1 -0
- package/src/auth/authorization/orchestrated.authorization.d.ts +242 -0
- package/src/auth/authorization/orchestrated.authorization.js +306 -0
- package/src/auth/authorization/orchestrated.authorization.js.map +1 -0
- package/src/auth/authorization/public.authorization.d.ts +91 -0
- package/src/auth/authorization/public.authorization.js +132 -0
- package/src/auth/authorization/public.authorization.js.map +1 -0
- package/src/auth/authorization/transparent.authorization.d.ts +130 -0
- package/src/auth/authorization/transparent.authorization.js +147 -0
- package/src/auth/authorization/transparent.authorization.js.map +1 -0
- package/src/auth/consent/consent.types.d.ts +111 -0
- package/src/auth/consent/consent.types.js +119 -0
- package/src/auth/consent/consent.types.js.map +1 -0
- package/src/auth/consent/index.d.ts +1 -0
- package/src/auth/consent/index.js +13 -0
- package/src/auth/consent/index.js.map +1 -0
- package/src/auth/detection/auth-provider-detection.d.ts +84 -0
- package/src/auth/detection/auth-provider-detection.js +230 -0
- package/src/auth/detection/auth-provider-detection.js.map +1 -0
- package/src/auth/detection/index.d.ts +1 -0
- package/src/auth/detection/index.js +15 -0
- package/src/auth/detection/index.js.map +1 -0
- package/src/auth/flows/auth.verify.flow.d.ts +110 -0
- package/src/auth/flows/auth.verify.flow.js +379 -0
- package/src/auth/flows/auth.verify.flow.js.map +1 -0
- package/src/auth/flows/oauth.authorize.flow.d.ts +118 -164
- package/src/auth/flows/oauth.authorize.flow.js +701 -33
- package/src/auth/flows/oauth.authorize.flow.js.map +1 -1
- package/src/auth/flows/oauth.callback.flow.d.ts +117 -0
- package/src/auth/flows/oauth.callback.flow.js +357 -0
- package/src/auth/flows/oauth.callback.flow.js.map +1 -0
- package/src/auth/flows/oauth.register.flow.d.ts +32 -125
- package/src/auth/flows/oauth.token.flow.d.ts +52 -154
- package/src/auth/flows/oauth.token.flow.js +193 -55
- package/src/auth/flows/oauth.token.flow.js.map +1 -1
- package/src/auth/flows/session.verify.flow.d.ts +66 -321
- package/src/auth/flows/session.verify.flow.js +107 -18
- package/src/auth/flows/session.verify.flow.js.map +1 -1
- package/src/auth/flows/well-known.jwks.flow.d.ts +34 -205
- package/src/auth/flows/well-known.jwks.flow.js +15 -8
- package/src/auth/flows/well-known.jwks.flow.js.map +1 -1
- package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +48 -223
- package/src/auth/flows/well-known.oauth-authorization-server.flow.js +2 -3
- package/src/auth/flows/well-known.oauth-authorization-server.flow.js.map +1 -1
- package/src/auth/flows/well-known.prm.flow.d.ts +19 -120
- package/src/auth/flows/well-known.prm.flow.js +3 -4
- package/src/auth/flows/well-known.prm.flow.js.map +1 -1
- package/src/auth/instances/instance.local-primary-auth.d.ts +91 -4
- package/src/auth/instances/instance.local-primary-auth.js +236 -6
- package/src/auth/instances/instance.local-primary-auth.js.map +1 -1
- package/src/auth/instances/instance.remote-primary-auth.d.ts +4 -3
- package/src/auth/instances/instance.remote-primary-auth.js +2 -2
- package/src/auth/instances/instance.remote-primary-auth.js.map +1 -1
- package/src/auth/session/authorization-vault.d.ts +611 -0
- package/src/auth/session/authorization-vault.js +817 -0
- package/src/auth/session/authorization-vault.js.map +1 -0
- package/src/auth/session/authorization.store.d.ts +301 -0
- package/src/auth/session/authorization.store.js +323 -0
- package/src/auth/session/authorization.store.js.map +1 -0
- package/src/auth/session/encrypted-authorization-vault.d.ts +181 -0
- package/src/auth/session/encrypted-authorization-vault.js +493 -0
- package/src/auth/session/encrypted-authorization-vault.js.map +1 -0
- package/src/auth/session/index.d.ts +4 -4
- package/src/auth/session/index.js +11 -7
- package/src/auth/session/index.js.map +1 -1
- package/src/auth/session/session.schema.d.ts +1 -1
- package/src/auth/session/session.service.d.ts +1 -1
- package/src/auth/session/transport-session.manager.d.ts +101 -0
- package/src/auth/session/transport-session.manager.js +300 -0
- package/src/auth/session/transport-session.manager.js.map +1 -0
- package/src/auth/session/transport-session.types.d.ts +457 -0
- package/src/auth/session/transport-session.types.js +110 -0
- package/src/auth/session/transport-session.types.js.map +1 -0
- package/src/auth/session/utils/session-id.utils.d.ts +14 -2
- package/src/auth/session/utils/session-id.utils.js +68 -19
- package/src/auth/session/utils/session-id.utils.js.map +1 -1
- package/src/auth/session/vault-encryption.d.ts +189 -0
- package/src/auth/session/vault-encryption.js +263 -0
- package/src/auth/session/vault-encryption.js.map +1 -0
- package/src/auth/ui/base-layout.d.ts +188 -0
- package/src/auth/ui/base-layout.js +292 -0
- package/src/auth/ui/base-layout.js.map +1 -0
- package/src/auth/ui/htmx-templates.d.ts +135 -0
- package/src/auth/ui/htmx-templates.js +433 -0
- package/src/auth/ui/htmx-templates.js.map +1 -0
- package/src/auth/ui/index.d.ts +11 -0
- package/src/auth/ui/index.js +35 -0
- package/src/auth/ui/index.js.map +1 -0
- package/src/auth/utils/audience.validator.d.ts +129 -0
- package/src/auth/utils/audience.validator.js +196 -0
- package/src/auth/utils/audience.validator.js.map +1 -0
- package/src/auth/utils/index.d.ts +2 -0
- package/src/auth/utils/index.js +7 -0
- package/src/auth/utils/index.js.map +1 -0
- package/src/auth/utils/www-authenticate.utils.d.ts +97 -0
- package/src/auth/utils/www-authenticate.utils.js +183 -0
- package/src/auth/utils/www-authenticate.utils.js.map +1 -0
- package/src/common/common.schema.d.ts +2 -16
- package/src/common/constants.d.ts +3 -0
- package/src/common/constants.js +6 -1
- package/src/common/constants.js.map +1 -1
- package/src/common/decorators/decorator-utils.d.ts +131 -0
- package/src/common/decorators/decorator-utils.js +195 -0
- package/src/common/decorators/decorator-utils.js.map +1 -0
- package/src/common/decorators/front-mcp.decorator.js +3 -2
- package/src/common/decorators/front-mcp.decorator.js.map +1 -1
- package/src/common/decorators/hook.decorator.d.ts +58 -2
- package/src/common/decorators/hook.decorator.js +127 -17
- package/src/common/decorators/hook.decorator.js.map +1 -1
- package/src/common/decorators/plugin.decorator.d.ts +1 -1
- package/src/common/decorators/plugin.decorator.js +11 -10
- package/src/common/decorators/plugin.decorator.js.map +1 -1
- package/src/common/decorators/resource.decorator.d.ts +32 -3
- package/src/common/decorators/resource.decorator.js +46 -4
- package/src/common/decorators/resource.decorator.js.map +1 -1
- package/src/common/decorators/tool.decorator.d.ts +54 -5
- package/src/common/decorators/tool.decorator.js.map +1 -1
- package/src/common/dynamic/dynamic.plugin.d.ts +22 -11
- package/src/common/dynamic/dynamic.plugin.js +7 -1
- package/src/common/dynamic/dynamic.plugin.js.map +1 -1
- package/src/common/entries/prompt.entry.d.ts +46 -2
- package/src/common/entries/prompt.entry.js +10 -0
- package/src/common/entries/prompt.entry.js.map +1 -1
- package/src/common/entries/resource.entry.d.ts +69 -6
- package/src/common/entries/resource.entry.js +27 -3
- package/src/common/entries/resource.entry.js.map +1 -1
- package/src/common/entries/scope.entry.d.ts +5 -1
- package/src/common/entries/scope.entry.js +3 -3
- package/src/common/entries/scope.entry.js.map +1 -1
- package/src/common/flow/flow.utils.d.ts +56 -0
- package/src/common/flow/flow.utils.js +96 -0
- package/src/common/flow/flow.utils.js.map +1 -0
- package/src/common/index.d.ts +2 -2
- package/src/common/index.js +2 -2
- package/src/common/index.js.map +1 -1
- package/src/common/interfaces/execution-context.interface.d.ts +59 -0
- package/src/common/interfaces/execution-context.interface.js +81 -0
- package/src/common/interfaces/execution-context.interface.js.map +1 -0
- package/src/common/interfaces/flow.interface.d.ts +1 -1
- package/src/common/interfaces/flow.interface.js.map +1 -1
- package/src/common/interfaces/index.d.ts +1 -0
- package/src/common/interfaces/index.js +1 -0
- package/src/common/interfaces/index.js.map +1 -1
- package/src/common/interfaces/internal/primary-auth-provider.interface.d.ts +17 -2
- package/src/common/interfaces/internal/primary-auth-provider.interface.js +52 -4
- package/src/common/interfaces/internal/primary-auth-provider.interface.js.map +1 -1
- package/src/common/interfaces/internal/registry.interface.d.ts +16 -2
- package/src/common/interfaces/internal/registry.interface.js.map +1 -1
- package/src/common/interfaces/plugin.interface.js.map +1 -1
- package/src/common/interfaces/prompt.interface.d.ts +53 -4
- package/src/common/interfaces/prompt.interface.js +78 -0
- package/src/common/interfaces/prompt.interface.js.map +1 -1
- package/src/common/interfaces/resource.interface.d.ts +47 -17
- package/src/common/interfaces/resource.interface.js +53 -0
- package/src/common/interfaces/resource.interface.js.map +1 -1
- package/src/common/interfaces/tool.interface.d.ts +39 -22
- package/src/common/interfaces/tool.interface.js +61 -34
- package/src/common/interfaces/tool.interface.js.map +1 -1
- package/src/common/metadata/adapter.metadata.d.ts +1 -9
- package/src/common/metadata/app.metadata.d.ts +425 -730
- package/src/common/metadata/auth-provider.metadata.d.ts +2 -12
- package/src/common/metadata/flow.metadata.d.ts +10 -25
- package/src/common/metadata/front-mcp.metadata.d.ts +602 -1023
- package/src/common/metadata/front-mcp.metadata.js +6 -4
- package/src/common/metadata/front-mcp.metadata.js.map +1 -1
- package/src/common/metadata/hook.metadata.d.ts +1 -1
- package/src/common/metadata/hook.metadata.js.map +1 -1
- package/src/common/metadata/index.d.ts +1 -0
- package/src/common/metadata/index.js +1 -0
- package/src/common/metadata/index.js.map +1 -1
- package/src/common/metadata/logger.metadata.d.ts +1 -9
- package/src/common/metadata/plugin.metadata.d.ts +8 -30
- package/src/common/metadata/prompt.metadata.d.ts +4 -161
- package/src/common/metadata/provider.metadata.d.ts +2 -12
- package/src/common/metadata/resource.metadata.d.ts +6 -98
- package/src/common/metadata/resource.metadata.js +15 -6
- package/src/common/metadata/resource.metadata.js.map +1 -1
- package/src/common/metadata/tool-ui.metadata.d.ts +10 -0
- package/src/common/metadata/tool-ui.metadata.js +12 -0
- package/src/common/metadata/tool-ui.metadata.js.map +1 -0
- package/src/common/metadata/tool.metadata.d.ts +78 -199
- package/src/common/metadata/tool.metadata.js +11 -14
- package/src/common/metadata/tool.metadata.js.map +1 -1
- package/src/common/providers/base-config.provider.d.ts +84 -0
- package/src/common/providers/base-config.provider.js +128 -0
- package/src/common/providers/base-config.provider.js.map +1 -0
- package/src/common/records/plugin.record.d.ts +5 -6
- package/src/common/records/plugin.record.js.map +1 -1
- package/src/common/records/prompt.record.js.map +1 -1
- package/src/common/records/resource.record.d.ts +17 -1
- package/src/common/records/resource.record.js +12 -6
- package/src/common/records/resource.record.js.map +1 -1
- package/src/common/records/tool.record.js.map +1 -1
- package/src/common/schemas/annotated-class.schema.d.ts +9 -9
- package/src/common/schemas/annotated-class.schema.js +92 -27
- package/src/common/schemas/annotated-class.schema.js.map +1 -1
- package/src/common/schemas/http-input.schema.d.ts +6 -30
- package/src/common/schemas/http-output.schema.d.ts +326 -1630
- package/src/common/schemas/http-output.schema.js +39 -1
- package/src/common/schemas/http-output.schema.js.map +1 -1
- package/src/common/tokens/front-mcp.tokens.js +4 -1
- package/src/common/tokens/front-mcp.tokens.js.map +1 -1
- package/src/common/tokens/resource.tokens.d.ts +2 -0
- package/src/common/tokens/resource.tokens.js +4 -1
- package/src/common/tokens/resource.tokens.js.map +1 -1
- package/src/common/tokens/tool.tokens.d.ts +2 -0
- package/src/common/tokens/tool.tokens.js +2 -0
- package/src/common/tokens/tool.tokens.js.map +1 -1
- package/src/common/types/auth/jwt.types.d.ts +5 -31
- package/src/common/types/auth/session.types.d.ts +97 -192
- package/src/common/types/auth/session.types.js +24 -11
- package/src/common/types/auth/session.types.js.map +1 -1
- package/src/common/types/options/auth.options.d.ts +1013 -490
- package/src/common/types/options/auth.options.js +554 -36
- package/src/common/types/options/auth.options.js.map +1 -1
- package/src/common/types/options/http.options.d.ts +1 -9
- package/src/common/types/options/logging.options.d.ts +7 -13
- package/src/common/types/options/logging.options.js +4 -0
- package/src/common/types/options/logging.options.js.map +1 -1
- package/src/common/types/options/server-info.options.d.ts +3 -31
- package/src/common/types/options/session.options.d.ts +90 -10
- package/src/common/types/options/session.options.js +26 -3
- package/src/common/types/options/session.options.js.map +1 -1
- package/src/common/utils/decide-request-intent.utils.d.ts +8 -46
- package/src/common/utils/decide-request-intent.utils.js +88 -23
- package/src/common/utils/decide-request-intent.utils.js.map +1 -1
- package/src/completion/flows/complete.flow.d.ts +74 -0
- package/src/completion/flows/complete.flow.js +199 -0
- package/src/completion/flows/complete.flow.js.map +1 -0
- package/src/errors/authorization-required.error.d.ts +189 -0
- package/src/errors/authorization-required.error.js +274 -0
- package/src/errors/authorization-required.error.js.map +1 -0
- package/src/errors/index.d.ts +2 -1
- package/src/errors/index.js +17 -1
- package/src/errors/index.js.map +1 -1
- package/src/errors/mcp.error.d.ts +101 -1
- package/src/errors/mcp.error.js +147 -2
- package/src/errors/mcp.error.js.map +1 -1
- package/src/flows/flow.instance.js +4 -3
- package/src/flows/flow.instance.js.map +1 -1
- package/src/flows/flow.registry.js.map +1 -1
- package/src/flows/flow.stages.js +14 -11
- package/src/flows/flow.stages.js.map +1 -1
- package/src/front-mcp/front-mcp.providers.d.ts +464 -102
- package/src/front-mcp/front-mcp.providers.js +3 -5
- package/src/front-mcp/front-mcp.providers.js.map +1 -1
- package/src/hooks/hook.instance.d.ts +1 -1
- package/src/hooks/hook.instance.js +5 -2
- package/src/hooks/hook.instance.js.map +1 -1
- package/src/hooks/hook.registry.js +7 -5
- package/src/hooks/hook.registry.js.map +1 -1
- package/src/index.d.ts +28 -9
- package/src/index.js +5 -1
- package/src/index.js.map +1 -1
- package/src/logger/instances/instance.logger.js +3 -2
- package/src/logger/instances/instance.logger.js.map +1 -1
- package/src/logger/logger.registry.js +7 -2
- package/src/logger/logger.registry.js.map +1 -1
- package/src/logging/flows/set-level.flow.d.ts +62 -0
- package/src/logging/flows/set-level.flow.js +108 -0
- package/src/logging/flows/set-level.flow.js.map +1 -0
- package/src/mcp-apps/csp.d.ts +111 -0
- package/src/mcp-apps/csp.js +267 -0
- package/src/mcp-apps/csp.js.map +1 -0
- package/src/mcp-apps/index.d.ts +23 -0
- package/src/mcp-apps/index.js +91 -0
- package/src/mcp-apps/index.js.map +1 -0
- package/src/mcp-apps/schemas.d.ts +403 -0
- package/src/mcp-apps/schemas.js +345 -0
- package/src/mcp-apps/schemas.js.map +1 -0
- package/src/mcp-apps/template.d.ts +94 -0
- package/src/mcp-apps/template.js +419 -0
- package/src/mcp-apps/template.js.map +1 -0
- package/src/mcp-apps/types.d.ts +323 -0
- package/src/mcp-apps/types.js +59 -0
- package/src/mcp-apps/types.js.map +1 -0
- package/src/notification/index.d.ts +1 -0
- package/src/notification/index.js +13 -0
- package/src/notification/index.js.map +1 -0
- package/src/notification/notification.service.d.ts +378 -0
- package/src/notification/notification.service.js +727 -0
- package/src/notification/notification.service.js.map +1 -0
- package/src/plugin/plugin.registry.js +12 -9
- package/src/plugin/plugin.registry.js.map +1 -1
- package/src/prompt/flows/get-prompt.flow.d.ts +153 -0
- package/src/prompt/flows/get-prompt.flow.js +214 -0
- package/src/prompt/flows/get-prompt.flow.js.map +1 -0
- package/src/prompt/flows/prompts-list.flow.d.ts +67 -0
- package/src/prompt/flows/prompts-list.flow.js +176 -0
- package/src/prompt/flows/prompts-list.flow.js.map +1 -0
- package/src/prompt/index.d.ts +7 -0
- package/src/prompt/index.js +17 -0
- package/src/prompt/index.js.map +1 -0
- package/src/prompt/prompt.events.d.ts +17 -0
- package/src/prompt/prompt.events.js +25 -0
- package/src/prompt/prompt.events.js.map +1 -0
- package/src/prompt/prompt.instance.d.ts +30 -0
- package/src/prompt/prompt.instance.js +120 -0
- package/src/prompt/prompt.instance.js.map +1 -0
- package/src/prompt/prompt.registry.d.ts +79 -12
- package/src/prompt/prompt.registry.js +360 -15
- package/src/prompt/prompt.registry.js.map +1 -1
- package/src/prompt/prompt.types.d.ts +26 -0
- package/src/prompt/prompt.types.js +11 -0
- package/src/prompt/prompt.types.js.map +1 -0
- package/src/prompt/prompt.utils.d.ts +26 -0
- package/src/prompt/prompt.utils.js +136 -0
- package/src/prompt/prompt.utils.js.map +1 -0
- package/src/provider/provider.registry.d.ts +12 -5
- package/src/provider/provider.registry.js +30 -138
- package/src/provider/provider.registry.js.map +1 -1
- package/src/regsitry/registry.base.d.ts +1 -1
- package/src/regsitry/registry.base.js.map +1 -1
- package/src/resource/flows/read-resource.flow.d.ts +91 -0
- package/src/resource/flows/read-resource.flow.js +270 -0
- package/src/resource/flows/read-resource.flow.js.map +1 -0
- package/src/resource/flows/resource-templates-list.flow.d.ts +64 -0
- package/src/resource/flows/resource-templates-list.flow.js +191 -0
- package/src/resource/flows/resource-templates-list.flow.js.map +1 -0
- package/src/resource/flows/resources-list.flow.d.ts +64 -0
- package/src/resource/flows/resources-list.flow.js +196 -0
- package/src/resource/flows/resources-list.flow.js.map +1 -0
- package/src/resource/flows/subscribe-resource.flow.d.ts +45 -0
- package/src/resource/flows/subscribe-resource.flow.js +123 -0
- package/src/resource/flows/subscribe-resource.flow.js.map +1 -0
- package/src/resource/flows/unsubscribe-resource.flow.d.ts +44 -0
- package/src/resource/flows/unsubscribe-resource.flow.js +107 -0
- package/src/resource/flows/unsubscribe-resource.flow.js.map +1 -0
- package/src/resource/index.d.ts +8 -0
- package/src/resource/index.js +20 -0
- package/src/resource/index.js.map +1 -0
- package/src/resource/resource.events.d.ts +24 -0
- package/src/resource/resource.events.js +17 -0
- package/src/resource/resource.events.js.map +1 -0
- package/src/resource/resource.instance.d.ts +35 -0
- package/src/resource/resource.instance.js +163 -0
- package/src/resource/resource.instance.js.map +1 -0
- package/src/resource/resource.registry.d.ts +106 -12
- package/src/resource/resource.registry.js +449 -13
- package/src/resource/resource.registry.js.map +1 -1
- package/src/resource/resource.types.d.ts +35 -0
- package/src/resource/resource.types.js +11 -0
- package/src/resource/resource.types.js.map +1 -0
- package/src/resource/resource.utils.d.ts +30 -0
- package/src/resource/resource.utils.js +151 -0
- package/src/resource/resource.utils.js.map +1 -0
- package/src/scope/flows/http.request.flow.d.ts +48 -330
- package/src/scope/flows/http.request.flow.js +306 -78
- package/src/scope/flows/http.request.flow.js.map +1 -1
- package/src/scope/scope.instance.d.ts +12 -0
- package/src/scope/scope.instance.js +145 -15
- package/src/scope/scope.instance.js.map +1 -1
- package/src/tool/flows/call-tool.flow.d.ts +64 -1110
- package/src/tool/flows/call-tool.flow.js +303 -15
- package/src/tool/flows/call-tool.flow.js.map +1 -1
- package/src/tool/flows/tools-list.flow.d.ts +32 -473
- package/src/tool/flows/tools-list.flow.js +111 -10
- package/src/tool/flows/tools-list.flow.js.map +1 -1
- package/src/tool/tool.events.d.ts +8 -1
- package/src/tool/tool.events.js.map +1 -1
- package/src/tool/tool.instance.d.ts +3 -1
- package/src/tool/tool.instance.js +17 -3
- package/src/tool/tool.instance.js.map +1 -1
- package/src/tool/tool.registry.d.ts +7 -1
- package/src/tool/tool.registry.js +26 -10
- package/src/tool/tool.registry.js.map +1 -1
- package/src/tool/tool.types.d.ts +4 -4
- package/src/tool/tool.types.js.map +1 -1
- package/src/tool/tool.utils.d.ts +3 -12
- package/src/tool/tool.utils.js +39 -193
- package/src/tool/tool.utils.js.map +1 -1
- package/src/tool/ui/index.d.ts +22 -0
- package/src/tool/ui/index.js +63 -0
- package/src/tool/ui/index.js.map +1 -0
- package/src/tool/ui/platform-adapters.d.ts +10 -0
- package/src/tool/ui/platform-adapters.js +18 -0
- package/src/tool/ui/platform-adapters.js.map +1 -0
- package/src/tool/ui/template-helpers.d.ts +46 -0
- package/src/tool/ui/template-helpers.js +112 -0
- package/src/tool/ui/template-helpers.js.map +1 -0
- package/src/tool/ui/ui-resource-template.d.ts +34 -0
- package/src/tool/ui/ui-resource-template.js +64 -0
- package/src/tool/ui/ui-resource-template.js.map +1 -0
- package/src/tool/ui/ui-resource.handler.d.ts +74 -0
- package/src/tool/ui/ui-resource.handler.js +129 -0
- package/src/tool/ui/ui-resource.handler.js.map +1 -0
- package/src/transport/adapters/transport.local.adapter.d.ts +2 -2
- package/src/transport/adapters/transport.local.adapter.js +28 -7
- package/src/transport/adapters/transport.local.adapter.js.map +1 -1
- package/src/transport/adapters/transport.sse.adapter.d.ts +2 -2
- package/src/transport/adapters/transport.sse.adapter.js +4 -3
- package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
- package/src/transport/adapters/transport.streamable-http.adapter.d.ts +10 -3
- package/src/transport/adapters/transport.streamable-http.adapter.js +54 -8
- package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
- package/src/transport/flows/handle.sse.flow.d.ts +29 -63
- package/src/transport/flows/handle.sse.flow.js +78 -10
- package/src/transport/flows/handle.sse.flow.js.map +1 -1
- package/src/transport/flows/handle.stateless-http.flow.d.ts +29 -0
- package/src/transport/flows/handle.stateless-http.flow.js +102 -0
- package/src/transport/flows/handle.stateless-http.flow.js.map +1 -0
- package/src/transport/flows/handle.streamable-http.flow.d.ts +32 -64
- package/src/transport/flows/handle.streamable-http.flow.js +158 -26
- package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
- package/src/transport/legacy/legacy.sse.tranporter.d.ts +9 -0
- package/src/transport/legacy/legacy.sse.tranporter.js +17 -2
- package/src/transport/legacy/legacy.sse.tranporter.js.map +1 -1
- package/src/transport/mcp-handlers/call-tool-request.handler.js +27 -1
- package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
- package/src/transport/mcp-handlers/complete-request.handler.d.ts +69 -0
- package/src/transport/mcp-handlers/complete-request.handler.js +11 -0
- package/src/transport/mcp-handlers/complete-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/get-prompt-request.handler.d.ts +87 -0
- package/src/transport/mcp-handlers/get-prompt-request.handler.js +11 -0
- package/src/transport/mcp-handlers/get-prompt-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/index.d.ts +517 -208
- package/src/transport/mcp-handlers/index.js +39 -2
- package/src/transport/mcp-handlers/index.js.map +1 -1
- package/src/transport/mcp-handlers/initialize-request.handler.d.ts +1 -1
- package/src/transport/mcp-handlers/initialize-request.handler.js +73 -7
- package/src/transport/mcp-handlers/initialize-request.handler.js.map +1 -1
- package/src/transport/mcp-handlers/list-prompts-request.handler.d.ts +54 -0
- package/src/transport/mcp-handlers/list-prompts-request.handler.js +11 -0
- package/src/transport/mcp-handlers/list-prompts-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.d.ts +51 -0
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.js +12 -0
- package/src/transport/mcp-handlers/list-resource-templates-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/list-resources-request.handler.d.ts +51 -0
- package/src/transport/mcp-handlers/list-resources-request.handler.js +12 -0
- package/src/transport/mcp-handlers/list-resources-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +19 -146
- package/src/transport/mcp-handlers/logging-set-level-request.handler.d.ts +46 -0
- package/src/transport/mcp-handlers/logging-set-level-request.handler.js +34 -0
- package/src/transport/mcp-handlers/logging-set-level-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/mcp-handlers.types.d.ts +3 -7
- package/src/transport/mcp-handlers/mcp-handlers.types.js.map +1 -1
- package/src/transport/mcp-handlers/read-resource-request.handler.d.ts +46 -0
- package/src/transport/mcp-handlers/read-resource-request.handler.js +12 -0
- package/src/transport/mcp-handlers/read-resource-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/roots-list-changed-notification.handler.d.ts +11 -0
- package/src/transport/mcp-handlers/roots-list-changed-notification.handler.js +26 -0
- package/src/transport/mcp-handlers/roots-list-changed-notification.handler.js.map +1 -0
- package/src/transport/mcp-handlers/subscribe-request.handler.d.ts +37 -0
- package/src/transport/mcp-handlers/subscribe-request.handler.js +34 -0
- package/src/transport/mcp-handlers/subscribe-request.handler.js.map +1 -0
- package/src/transport/mcp-handlers/unsubscribe-request.handler.d.ts +37 -0
- package/src/transport/mcp-handlers/unsubscribe-request.handler.js +34 -0
- package/src/transport/mcp-handlers/unsubscribe-request.handler.js.map +1 -0
- package/src/transport/transport.local.js +7 -2
- package/src/transport/transport.local.js.map +1 -1
- package/src/transport/transport.registry.d.ts +30 -0
- package/src/transport/transport.registry.js +84 -1
- package/src/transport/transport.registry.js.map +1 -1
- package/src/transport/transport.types.d.ts +3 -3
- package/src/transport/transport.types.js.map +1 -1
- package/src/utils/content.utils.d.ts +48 -0
- package/src/utils/content.utils.js +194 -0
- package/src/utils/content.utils.js.map +1 -0
- package/src/utils/index.d.ts +8 -0
- package/src/utils/index.js +55 -0
- package/src/utils/index.js.map +1 -0
- package/src/utils/lineage.utils.d.ts +40 -0
- package/src/utils/lineage.utils.js +82 -0
- package/src/utils/lineage.utils.js.map +1 -0
- package/src/utils/naming.utils.d.ts +46 -0
- package/src/utils/naming.utils.js +136 -0
- package/src/utils/naming.utils.js.map +1 -0
- package/src/utils/types.utils.d.ts +2 -2
- package/src/utils/types.utils.js.map +1 -1
- package/src/utils/uri-template.utils.d.ts +57 -0
- package/src/utils/uri-template.utils.js +113 -0
- package/src/utils/uri-template.utils.js.map +1 -0
- package/src/utils/uri-validation.utils.d.ts +40 -0
- package/src/utils/uri-validation.utils.js +76 -0
- package/src/utils/uri-validation.utils.js.map +1 -0
- package/src/__test-utils__/fixtures/hook.fixtures.d.ts +0 -46
- package/src/__test-utils__/fixtures/hook.fixtures.js +0 -114
- package/src/__test-utils__/fixtures/hook.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/index.d.ts +0 -7
- package/src/__test-utils__/fixtures/index.js +0 -11
- package/src/__test-utils__/fixtures/index.js.map +0 -1
- package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +0 -46
- package/src/__test-utils__/fixtures/plugin.fixtures.js +0 -127
- package/src/__test-utils__/fixtures/plugin.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/provider.fixtures.d.ts +0 -69
- package/src/__test-utils__/fixtures/provider.fixtures.js +0 -131
- package/src/__test-utils__/fixtures/provider.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/scope.fixtures.d.ts +0 -14
- package/src/__test-utils__/fixtures/scope.fixtures.js +0 -59
- package/src/__test-utils__/fixtures/scope.fixtures.js.map +0 -1
- package/src/__test-utils__/fixtures/tool.fixtures.d.ts +0 -36
- package/src/__test-utils__/fixtures/tool.fixtures.js +0 -91
- package/src/__test-utils__/fixtures/tool.fixtures.js.map +0 -1
- package/src/__test-utils__/helpers/assertion.helpers.d.ts +0 -45
- package/src/__test-utils__/helpers/assertion.helpers.js +0 -153
- package/src/__test-utils__/helpers/assertion.helpers.js.map +0 -1
- package/src/__test-utils__/helpers/async.helpers.d.ts +0 -48
- package/src/__test-utils__/helpers/async.helpers.js +0 -112
- package/src/__test-utils__/helpers/async.helpers.js.map +0 -1
- package/src/__test-utils__/helpers/index.d.ts +0 -6
- package/src/__test-utils__/helpers/index.js +0 -10
- package/src/__test-utils__/helpers/index.js.map +0 -1
- package/src/__test-utils__/helpers/setup.helpers.d.ts +0 -54
- package/src/__test-utils__/helpers/setup.helpers.js +0 -106
- package/src/__test-utils__/helpers/setup.helpers.js.map +0 -1
- package/src/__test-utils__/index.d.ts +0 -9
- package/src/__test-utils__/index.js +0 -14
- package/src/__test-utils__/index.js.map +0 -1
- package/src/__test-utils__/mocks/flow-instance.mock.d.ts +0 -50
- package/src/__test-utils__/mocks/flow-instance.mock.js +0 -72
- package/src/__test-utils__/mocks/flow-instance.mock.js.map +0 -1
- package/src/__test-utils__/mocks/hook-registry.mock.d.ts +0 -25
- package/src/__test-utils__/mocks/hook-registry.mock.js +0 -65
- package/src/__test-utils__/mocks/hook-registry.mock.js.map +0 -1
- package/src/__test-utils__/mocks/index.d.ts +0 -8
- package/src/__test-utils__/mocks/index.js +0 -12
- package/src/__test-utils__/mocks/index.js.map +0 -1
- package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +0 -43
- package/src/__test-utils__/mocks/plugin-registry.mock.js +0 -70
- package/src/__test-utils__/mocks/plugin-registry.mock.js.map +0 -1
- package/src/__test-utils__/mocks/provider-registry.mock.d.ts +0 -39
- package/src/__test-utils__/mocks/provider-registry.mock.js +0 -72
- package/src/__test-utils__/mocks/provider-registry.mock.js.map +0 -1
- package/src/__test-utils__/mocks/tool-registry.mock.d.ts +0 -43
- package/src/__test-utils__/mocks/tool-registry.mock.js +0 -79
- package/src/__test-utils__/mocks/tool-registry.mock.js.map +0 -1
- package/src/auth/path.utils.d.ts +0 -20
- package/src/auth/path.utils.js +0 -71
- package/src/auth/path.utils.js.map +0 -1
- package/src/common/decorators-old/async-with.decorator.d.ts +0 -10
- package/src/common/decorators-old/async-with.decorator.js +0 -24
- package/src/common/decorators-old/async-with.decorator.js.map +0 -1
- package/src/common/decorators-old/auth-hook.decorator.d.ts +0 -14
- package/src/common/decorators-old/auth-hook.decorator.js +0 -27
- package/src/common/decorators-old/auth-hook.decorator.js.map +0 -1
- package/src/common/decorators-old/session-hook.decorator.d.ts +0 -14
- package/src/common/decorators-old/session-hook.decorator.js +0 -27
- package/src/common/decorators-old/session-hook.decorator.js.map +0 -1
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Encrypted Authorization Vault
|
|
4
|
+
*
|
|
5
|
+
* A vault implementation that encrypts all sensitive data using a key
|
|
6
|
+
* derived from the client's JWT authorization token.
|
|
7
|
+
*
|
|
8
|
+
* Security Properties:
|
|
9
|
+
* - Zero-knowledge storage: Server cannot decrypt credentials
|
|
10
|
+
* - Client-side key: Encryption key derived from JWT (client must present token)
|
|
11
|
+
* - Authenticated encryption: AES-256-GCM prevents tampering
|
|
12
|
+
* - Per-vault keys: Each vault has a unique encryption key
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const vault = new EncryptedRedisVault(redis, encryption);
|
|
17
|
+
*
|
|
18
|
+
* // On each request, derive key from JWT and set context
|
|
19
|
+
* const key = encryption.deriveKeyFromToken(token, claims);
|
|
20
|
+
* vault.setEncryptionKey(key);
|
|
21
|
+
*
|
|
22
|
+
* // Now all operations automatically encrypt/decrypt
|
|
23
|
+
* await vault.addAppCredential(vaultId, credential);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.EncryptedRedisVault = exports.redisVaultEntrySchema = void 0;
|
|
28
|
+
exports.createEncryptedVault = createEncryptedVault;
|
|
29
|
+
const zod_1 = require("zod");
|
|
30
|
+
const node_crypto_1 = require("node:crypto");
|
|
31
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
32
|
+
const vault_encryption_1 = require("./vault-encryption");
|
|
33
|
+
// ============================================
|
|
34
|
+
// Encrypted Vault Entry Schema
|
|
35
|
+
// ============================================
|
|
36
|
+
/**
|
|
37
|
+
* What we store in Redis - minimal metadata + encrypted blob
|
|
38
|
+
*/
|
|
39
|
+
exports.redisVaultEntrySchema = zod_1.z.object({
|
|
40
|
+
/** Vault ID */
|
|
41
|
+
id: zod_1.z.string(),
|
|
42
|
+
/** User sub (for lookup) */
|
|
43
|
+
userSub: zod_1.z.string(),
|
|
44
|
+
/** User email (optional, for display) */
|
|
45
|
+
userEmail: zod_1.z.string().optional(),
|
|
46
|
+
/** User name (optional, for display) */
|
|
47
|
+
userName: zod_1.z.string().optional(),
|
|
48
|
+
/** Client ID */
|
|
49
|
+
clientId: zod_1.z.string(),
|
|
50
|
+
/** Creation timestamp */
|
|
51
|
+
createdAt: zod_1.z.number(),
|
|
52
|
+
/** Last access timestamp */
|
|
53
|
+
lastAccessAt: zod_1.z.number(),
|
|
54
|
+
/** Authorized app IDs (unencrypted for quick auth checks) */
|
|
55
|
+
authorizedAppIds: zod_1.z.array(zod_1.z.string()),
|
|
56
|
+
/** Skipped app IDs (unencrypted for quick checks) */
|
|
57
|
+
skippedAppIds: zod_1.z.array(zod_1.z.string()),
|
|
58
|
+
/** Pending auth request IDs (unencrypted for lookup) */
|
|
59
|
+
pendingAuthIds: zod_1.z.array(zod_1.z.string()),
|
|
60
|
+
/** Encrypted sensitive data blob */
|
|
61
|
+
encrypted: vault_encryption_1.encryptedDataSchema,
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Module-level AsyncLocalStorage for request-scoped encryption context.
|
|
65
|
+
* This ensures concurrent requests don't interfere with each other's encryption keys.
|
|
66
|
+
*/
|
|
67
|
+
const encryptionContextStorage = new node_async_hooks_1.AsyncLocalStorage();
|
|
68
|
+
// ============================================
|
|
69
|
+
// Encrypted Redis Vault Implementation
|
|
70
|
+
// ============================================
|
|
71
|
+
/**
|
|
72
|
+
* Redis vault with client-side encryption
|
|
73
|
+
*
|
|
74
|
+
* All sensitive data (tokens, credentials, consent, pending auths)
|
|
75
|
+
* is encrypted using a key derived from the client's JWT.
|
|
76
|
+
*
|
|
77
|
+
* Use `runWithContext()` to set encryption context for concurrent safety.
|
|
78
|
+
*/
|
|
79
|
+
class EncryptedRedisVault {
|
|
80
|
+
redis;
|
|
81
|
+
encryption;
|
|
82
|
+
namespace;
|
|
83
|
+
constructor(
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
redis, encryption, namespace = 'vault:') {
|
|
86
|
+
this.redis = redis;
|
|
87
|
+
this.encryption = encryption;
|
|
88
|
+
this.namespace = namespace;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Run a callback with encryption context set for the current async scope.
|
|
92
|
+
* This is the recommended way to set encryption context as it is safe for
|
|
93
|
+
* concurrent requests (each request gets its own isolated context).
|
|
94
|
+
*
|
|
95
|
+
* @param context - Encryption context with key and vaultId
|
|
96
|
+
* @param fn - Async function to run with the context
|
|
97
|
+
* @returns The result of the callback
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const result = await vault.runWithContext({ key, vaultId }, async () => {
|
|
102
|
+
* await vault.get(id);
|
|
103
|
+
* await vault.update(id, data);
|
|
104
|
+
* return 'done';
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
runWithContext(context, fn) {
|
|
109
|
+
return encryptionContextStorage.run(context, fn);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get current encryption key from AsyncLocalStorage.
|
|
113
|
+
*/
|
|
114
|
+
getKey() {
|
|
115
|
+
const asyncContext = encryptionContextStorage.getStore();
|
|
116
|
+
if (asyncContext) {
|
|
117
|
+
return asyncContext.key;
|
|
118
|
+
}
|
|
119
|
+
throw new Error('Encryption context not set. Use runWithContext() before performing vault operations.');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Create Redis key from vault ID
|
|
123
|
+
*/
|
|
124
|
+
redisKey(id) {
|
|
125
|
+
return `${this.namespace}${id}`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create credential key from appId and providerId
|
|
129
|
+
*/
|
|
130
|
+
credentialKey(appId, providerId) {
|
|
131
|
+
return `${appId}:${providerId}`;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Encrypt sensitive data
|
|
135
|
+
*/
|
|
136
|
+
encryptSensitive(data) {
|
|
137
|
+
return this.encryption.encryptObject(data, this.getKey());
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Decrypt sensitive data
|
|
141
|
+
*/
|
|
142
|
+
decryptSensitive(encrypted) {
|
|
143
|
+
return this.encryption.decryptObject(encrypted, this.getKey());
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Convert Redis entry to full vault entry (decrypts sensitive data)
|
|
147
|
+
*/
|
|
148
|
+
toVaultEntry(redisEntry) {
|
|
149
|
+
const sensitive = this.decryptSensitive(redisEntry.encrypted);
|
|
150
|
+
return {
|
|
151
|
+
id: redisEntry.id,
|
|
152
|
+
userSub: redisEntry.userSub,
|
|
153
|
+
userEmail: redisEntry.userEmail,
|
|
154
|
+
userName: redisEntry.userName,
|
|
155
|
+
clientId: redisEntry.clientId,
|
|
156
|
+
createdAt: redisEntry.createdAt,
|
|
157
|
+
lastAccessAt: redisEntry.lastAccessAt,
|
|
158
|
+
appCredentials: sensitive.appCredentials,
|
|
159
|
+
consent: sensitive.consent,
|
|
160
|
+
federated: sensitive.federated,
|
|
161
|
+
pendingAuths: sensitive.pendingAuths,
|
|
162
|
+
authorizedAppIds: redisEntry.authorizedAppIds,
|
|
163
|
+
skippedAppIds: redisEntry.skippedAppIds,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Convert vault entry to Redis entry (encrypts sensitive data)
|
|
168
|
+
*/
|
|
169
|
+
toRedisEntry(entry) {
|
|
170
|
+
const sensitive = {
|
|
171
|
+
appCredentials: entry.appCredentials,
|
|
172
|
+
consent: entry.consent,
|
|
173
|
+
federated: entry.federated,
|
|
174
|
+
pendingAuths: entry.pendingAuths,
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
id: entry.id,
|
|
178
|
+
userSub: entry.userSub,
|
|
179
|
+
userEmail: entry.userEmail,
|
|
180
|
+
userName: entry.userName,
|
|
181
|
+
clientId: entry.clientId,
|
|
182
|
+
createdAt: entry.createdAt,
|
|
183
|
+
lastAccessAt: entry.lastAccessAt,
|
|
184
|
+
authorizedAppIds: entry.authorizedAppIds,
|
|
185
|
+
skippedAppIds: entry.skippedAppIds,
|
|
186
|
+
pendingAuthIds: entry.pendingAuths.map((p) => p.id),
|
|
187
|
+
encrypted: this.encryptSensitive(sensitive),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Save entry to Redis
|
|
192
|
+
*/
|
|
193
|
+
async saveEntry(entry) {
|
|
194
|
+
const redisEntry = this.toRedisEntry(entry);
|
|
195
|
+
await this.redis.set(this.redisKey(entry.id), JSON.stringify(redisEntry));
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Load entry from Redis
|
|
199
|
+
*/
|
|
200
|
+
async loadEntry(id) {
|
|
201
|
+
const data = await this.redis.get(this.redisKey(id));
|
|
202
|
+
if (!data)
|
|
203
|
+
return null;
|
|
204
|
+
try {
|
|
205
|
+
const redisEntry = exports.redisVaultEntrySchema.parse(JSON.parse(data));
|
|
206
|
+
return this.toVaultEntry(redisEntry);
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
// Could be decryption failure (wrong key) or corrupt data
|
|
210
|
+
throw new Error(`Failed to load vault ${id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// ============================================
|
|
214
|
+
// AuthorizationVault Interface Implementation
|
|
215
|
+
// ============================================
|
|
216
|
+
async create(params) {
|
|
217
|
+
const now = Date.now();
|
|
218
|
+
const entry = {
|
|
219
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
220
|
+
userSub: params.userSub,
|
|
221
|
+
userEmail: params.userEmail,
|
|
222
|
+
userName: params.userName,
|
|
223
|
+
clientId: params.clientId,
|
|
224
|
+
createdAt: now,
|
|
225
|
+
lastAccessAt: now,
|
|
226
|
+
appCredentials: {},
|
|
227
|
+
consent: params.consent,
|
|
228
|
+
federated: params.federated,
|
|
229
|
+
pendingAuths: [],
|
|
230
|
+
authorizedAppIds: params.authorizedAppIds ?? [],
|
|
231
|
+
skippedAppIds: params.skippedAppIds ?? [],
|
|
232
|
+
};
|
|
233
|
+
await this.saveEntry(entry);
|
|
234
|
+
return entry;
|
|
235
|
+
}
|
|
236
|
+
async get(id) {
|
|
237
|
+
const entry = await this.loadEntry(id);
|
|
238
|
+
if (!entry)
|
|
239
|
+
return null;
|
|
240
|
+
// Update last access time
|
|
241
|
+
entry.lastAccessAt = Date.now();
|
|
242
|
+
await this.saveEntry(entry);
|
|
243
|
+
return entry;
|
|
244
|
+
}
|
|
245
|
+
async update(id, updates) {
|
|
246
|
+
const entry = await this.loadEntry(id);
|
|
247
|
+
if (!entry) {
|
|
248
|
+
throw new Error(`Vault entry not found: ${id}`);
|
|
249
|
+
}
|
|
250
|
+
Object.assign(entry, updates, { lastAccessAt: Date.now() });
|
|
251
|
+
await this.saveEntry(entry);
|
|
252
|
+
}
|
|
253
|
+
async delete(id) {
|
|
254
|
+
await this.redis.del(this.redisKey(id));
|
|
255
|
+
}
|
|
256
|
+
async updateConsent(vaultId, consent) {
|
|
257
|
+
const entry = await this.loadEntry(vaultId);
|
|
258
|
+
if (!entry)
|
|
259
|
+
return;
|
|
260
|
+
entry.consent = consent;
|
|
261
|
+
entry.lastAccessAt = Date.now();
|
|
262
|
+
await this.saveEntry(entry);
|
|
263
|
+
}
|
|
264
|
+
async authorizeApp(vaultId, appId) {
|
|
265
|
+
const entry = await this.loadEntry(vaultId);
|
|
266
|
+
if (!entry)
|
|
267
|
+
return;
|
|
268
|
+
entry.skippedAppIds = entry.skippedAppIds.filter((id) => id !== appId);
|
|
269
|
+
if (!entry.authorizedAppIds.includes(appId)) {
|
|
270
|
+
entry.authorizedAppIds.push(appId);
|
|
271
|
+
}
|
|
272
|
+
entry.lastAccessAt = Date.now();
|
|
273
|
+
await this.saveEntry(entry);
|
|
274
|
+
}
|
|
275
|
+
async createPendingAuth(vaultId, params) {
|
|
276
|
+
const entry = await this.loadEntry(vaultId);
|
|
277
|
+
if (!entry) {
|
|
278
|
+
throw new Error(`Vault not found: ${vaultId}`);
|
|
279
|
+
}
|
|
280
|
+
const now = Date.now();
|
|
281
|
+
const pendingAuth = {
|
|
282
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
283
|
+
appId: params.appId,
|
|
284
|
+
toolId: params.toolId,
|
|
285
|
+
authUrl: params.authUrl,
|
|
286
|
+
requiredScopes: params.requiredScopes,
|
|
287
|
+
elicitId: params.elicitId,
|
|
288
|
+
createdAt: now,
|
|
289
|
+
expiresAt: now + (params.ttlMs ?? 10 * 60 * 1000),
|
|
290
|
+
status: 'pending',
|
|
291
|
+
};
|
|
292
|
+
entry.pendingAuths.push(pendingAuth);
|
|
293
|
+
entry.lastAccessAt = now;
|
|
294
|
+
await this.saveEntry(entry);
|
|
295
|
+
return pendingAuth;
|
|
296
|
+
}
|
|
297
|
+
async getPendingAuth(vaultId, pendingAuthId) {
|
|
298
|
+
const entry = await this.loadEntry(vaultId);
|
|
299
|
+
if (!entry)
|
|
300
|
+
return null;
|
|
301
|
+
const pendingAuth = entry.pendingAuths.find((p) => p.id === pendingAuthId);
|
|
302
|
+
if (!pendingAuth)
|
|
303
|
+
return null;
|
|
304
|
+
if (Date.now() > pendingAuth.expiresAt && pendingAuth.status === 'pending') {
|
|
305
|
+
pendingAuth.status = 'expired';
|
|
306
|
+
await this.saveEntry(entry);
|
|
307
|
+
}
|
|
308
|
+
return pendingAuth;
|
|
309
|
+
}
|
|
310
|
+
async completePendingAuth(vaultId, pendingAuthId) {
|
|
311
|
+
const entry = await this.loadEntry(vaultId);
|
|
312
|
+
if (!entry)
|
|
313
|
+
return;
|
|
314
|
+
const pendingAuth = entry.pendingAuths.find((p) => p.id === pendingAuthId);
|
|
315
|
+
if (pendingAuth) {
|
|
316
|
+
pendingAuth.status = 'completed';
|
|
317
|
+
// Authorize app inline (don't call authorizeApp which reloads entry)
|
|
318
|
+
entry.skippedAppIds = entry.skippedAppIds.filter((id) => id !== pendingAuth.appId);
|
|
319
|
+
if (!entry.authorizedAppIds.includes(pendingAuth.appId)) {
|
|
320
|
+
entry.authorizedAppIds.push(pendingAuth.appId);
|
|
321
|
+
}
|
|
322
|
+
entry.lastAccessAt = Date.now();
|
|
323
|
+
await this.saveEntry(entry);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async cancelPendingAuth(vaultId, pendingAuthId) {
|
|
327
|
+
const entry = await this.loadEntry(vaultId);
|
|
328
|
+
if (!entry)
|
|
329
|
+
return;
|
|
330
|
+
const pendingAuth = entry.pendingAuths.find((p) => p.id === pendingAuthId);
|
|
331
|
+
if (pendingAuth) {
|
|
332
|
+
pendingAuth.status = 'cancelled';
|
|
333
|
+
await this.saveEntry(entry);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
async isAppAuthorized(vaultId, appId) {
|
|
337
|
+
// Quick check without decryption - authorizedAppIds is unencrypted
|
|
338
|
+
const data = await this.redis.get(this.redisKey(vaultId));
|
|
339
|
+
if (!data)
|
|
340
|
+
return false;
|
|
341
|
+
try {
|
|
342
|
+
const parsed = JSON.parse(data);
|
|
343
|
+
return Array.isArray(parsed.authorizedAppIds) && parsed.authorizedAppIds.includes(appId);
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
async getPendingAuths(vaultId) {
|
|
350
|
+
const entry = await this.loadEntry(vaultId);
|
|
351
|
+
if (!entry)
|
|
352
|
+
return [];
|
|
353
|
+
const now = Date.now();
|
|
354
|
+
let updated = false;
|
|
355
|
+
const pending = entry.pendingAuths.filter((p) => {
|
|
356
|
+
if (now > p.expiresAt && p.status === 'pending') {
|
|
357
|
+
p.status = 'expired';
|
|
358
|
+
updated = true;
|
|
359
|
+
}
|
|
360
|
+
return p.status === 'pending';
|
|
361
|
+
});
|
|
362
|
+
if (updated) {
|
|
363
|
+
await this.saveEntry(entry);
|
|
364
|
+
}
|
|
365
|
+
return pending;
|
|
366
|
+
}
|
|
367
|
+
// ============================================
|
|
368
|
+
// App Credential Methods
|
|
369
|
+
// ============================================
|
|
370
|
+
async addAppCredential(vaultId, credential) {
|
|
371
|
+
const entry = await this.loadEntry(vaultId);
|
|
372
|
+
if (!entry)
|
|
373
|
+
return;
|
|
374
|
+
const shouldStore = await this.shouldStoreCredential(vaultId, credential.appId);
|
|
375
|
+
if (!shouldStore)
|
|
376
|
+
return;
|
|
377
|
+
const key = this.credentialKey(credential.appId, credential.providerId);
|
|
378
|
+
entry.appCredentials[key] = credential;
|
|
379
|
+
entry.lastAccessAt = Date.now();
|
|
380
|
+
await this.saveEntry(entry);
|
|
381
|
+
}
|
|
382
|
+
async removeAppCredential(vaultId, appId, providerId) {
|
|
383
|
+
const entry = await this.loadEntry(vaultId);
|
|
384
|
+
if (!entry)
|
|
385
|
+
return;
|
|
386
|
+
const key = this.credentialKey(appId, providerId);
|
|
387
|
+
delete entry.appCredentials[key];
|
|
388
|
+
entry.lastAccessAt = Date.now();
|
|
389
|
+
await this.saveEntry(entry);
|
|
390
|
+
}
|
|
391
|
+
async getAppCredentials(vaultId, appId) {
|
|
392
|
+
const entry = await this.loadEntry(vaultId);
|
|
393
|
+
if (!entry)
|
|
394
|
+
return [];
|
|
395
|
+
const prefix = `${appId}:`;
|
|
396
|
+
return Object.entries(entry.appCredentials)
|
|
397
|
+
.filter(([key]) => key.startsWith(prefix))
|
|
398
|
+
.map(([, cred]) => cred);
|
|
399
|
+
}
|
|
400
|
+
async getCredential(vaultId, appId, providerId) {
|
|
401
|
+
const entry = await this.loadEntry(vaultId);
|
|
402
|
+
if (!entry)
|
|
403
|
+
return null;
|
|
404
|
+
const key = this.credentialKey(appId, providerId);
|
|
405
|
+
return entry.appCredentials[key] ?? null;
|
|
406
|
+
}
|
|
407
|
+
async getAllCredentials(vaultId, filterByConsent = false) {
|
|
408
|
+
const entry = await this.loadEntry(vaultId);
|
|
409
|
+
if (!entry)
|
|
410
|
+
return [];
|
|
411
|
+
const allCredentials = Object.values(entry.appCredentials);
|
|
412
|
+
if (!filterByConsent || !entry.consent?.enabled) {
|
|
413
|
+
return allCredentials;
|
|
414
|
+
}
|
|
415
|
+
const consentedToolIds = new Set(entry.consent.selectedToolIds);
|
|
416
|
+
return allCredentials.filter((cred) => {
|
|
417
|
+
return Array.from(consentedToolIds).some((toolId) => toolId.startsWith(`${cred.appId}:`));
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
async updateCredential(vaultId, appId, providerId, updates) {
|
|
421
|
+
const entry = await this.loadEntry(vaultId);
|
|
422
|
+
if (!entry)
|
|
423
|
+
return;
|
|
424
|
+
const key = this.credentialKey(appId, providerId);
|
|
425
|
+
const credential = entry.appCredentials[key];
|
|
426
|
+
if (!credential)
|
|
427
|
+
return;
|
|
428
|
+
Object.assign(credential, updates);
|
|
429
|
+
entry.lastAccessAt = Date.now();
|
|
430
|
+
await this.saveEntry(entry);
|
|
431
|
+
}
|
|
432
|
+
async shouldStoreCredential(vaultId, appId, toolIds) {
|
|
433
|
+
const entry = await this.loadEntry(vaultId);
|
|
434
|
+
if (!entry)
|
|
435
|
+
return false;
|
|
436
|
+
if (!entry.consent?.enabled) {
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
if (toolIds && toolIds.length > 0) {
|
|
440
|
+
return toolIds.some((toolId) => entry.consent.selectedToolIds.includes(toolId));
|
|
441
|
+
}
|
|
442
|
+
const consentedToolIds = entry.consent.selectedToolIds;
|
|
443
|
+
return consentedToolIds.some((toolId) => toolId.startsWith(`${appId}:`));
|
|
444
|
+
}
|
|
445
|
+
async invalidateCredential(vaultId, appId, providerId, reason) {
|
|
446
|
+
await this.updateCredential(vaultId, appId, providerId, {
|
|
447
|
+
isValid: false,
|
|
448
|
+
invalidReason: reason,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
async refreshOAuthCredential(vaultId, appId, providerId, tokens) {
|
|
452
|
+
const entry = await this.loadEntry(vaultId);
|
|
453
|
+
if (!entry)
|
|
454
|
+
return;
|
|
455
|
+
const key = this.credentialKey(appId, providerId);
|
|
456
|
+
const credential = entry.appCredentials[key];
|
|
457
|
+
if (!credential || credential.credential.type !== 'oauth')
|
|
458
|
+
return;
|
|
459
|
+
// Update OAuth tokens
|
|
460
|
+
credential.credential.accessToken = tokens.accessToken;
|
|
461
|
+
if (tokens.refreshToken !== undefined) {
|
|
462
|
+
credential.credential.refreshToken = tokens.refreshToken;
|
|
463
|
+
}
|
|
464
|
+
if (tokens.expiresAt !== undefined) {
|
|
465
|
+
credential.credential.expiresAt = tokens.expiresAt;
|
|
466
|
+
credential.expiresAt = tokens.expiresAt;
|
|
467
|
+
}
|
|
468
|
+
credential.isValid = true;
|
|
469
|
+
credential.invalidReason = undefined;
|
|
470
|
+
entry.lastAccessAt = Date.now();
|
|
471
|
+
await this.saveEntry(entry);
|
|
472
|
+
}
|
|
473
|
+
async cleanup() {
|
|
474
|
+
// Redis cleanup would use SCAN to find and clean entries
|
|
475
|
+
// For encrypted vault, this needs careful handling
|
|
476
|
+
// as we can't read data without the encryption key
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
exports.EncryptedRedisVault = EncryptedRedisVault;
|
|
480
|
+
// ============================================
|
|
481
|
+
// Factory Function
|
|
482
|
+
// ============================================
|
|
483
|
+
/**
|
|
484
|
+
* Create an encrypted vault with the given configuration
|
|
485
|
+
*/
|
|
486
|
+
function createEncryptedVault(
|
|
487
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
488
|
+
redis, config = {}) {
|
|
489
|
+
const encryption = new vault_encryption_1.VaultEncryption({ pepper: config.pepper });
|
|
490
|
+
const vault = new EncryptedRedisVault(redis, encryption, config.namespace);
|
|
491
|
+
return { vault, encryption };
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=encrypted-authorization-vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted-authorization-vault.js","sourceRoot":"","sources":["../../../../src/auth/session/encrypted-authorization-vault.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Encrypted Authorization Vault\n *\n * A vault implementation that encrypts all sensitive data using a key\n * derived from the client's JWT authorization token.\n *\n * Security Properties:\n * - Zero-knowledge storage: Server cannot decrypt credentials\n * - Client-side key: Encryption key derived from JWT (client must present token)\n * - Authenticated encryption: AES-256-GCM prevents tampering\n * - Per-vault keys: Each vault has a unique encryption key\n *\n * Usage:\n * ```typescript\n * const vault = new EncryptedRedisVault(redis, encryption);\n *\n * // On each request, derive key from JWT and set context\n * const key = encryption.deriveKeyFromToken(token, claims);\n * vault.setEncryptionKey(key);\n *\n * // Now all operations automatically encrypt/decrypt\n * await vault.addAppCredential(vaultId, credential);\n * ```\n */\n\nimport { z } from 'zod';\nimport { randomUUID } from 'node:crypto';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { VaultEncryption, EncryptedData, VaultSensitiveData, encryptedDataSchema } from './vault-encryption';\nimport {\n AuthorizationVault,\n AuthorizationVaultEntry,\n AppCredential,\n VaultConsentRecord,\n VaultFederatedRecord,\n PendingIncrementalAuth,\n authorizationVaultEntrySchema,\n} from './authorization-vault';\n\n// ============================================\n// Encrypted Vault Entry Schema\n// ============================================\n\n/**\n * What we store in Redis - minimal metadata + encrypted blob\n */\nexport const redisVaultEntrySchema = z.object({\n /** Vault ID */\n id: z.string(),\n /** User sub (for lookup) */\n userSub: z.string(),\n /** User email (optional, for display) */\n userEmail: z.string().optional(),\n /** User name (optional, for display) */\n userName: z.string().optional(),\n /** Client ID */\n clientId: z.string(),\n /** Creation timestamp */\n createdAt: z.number(),\n /** Last access timestamp */\n lastAccessAt: z.number(),\n /** Authorized app IDs (unencrypted for quick auth checks) */\n authorizedAppIds: z.array(z.string()),\n /** Skipped app IDs (unencrypted for quick checks) */\n skippedAppIds: z.array(z.string()),\n /** Pending auth request IDs (unencrypted for lookup) */\n pendingAuthIds: z.array(z.string()),\n /** Encrypted sensitive data blob */\n encrypted: encryptedDataSchema,\n});\n\nexport type RedisVaultEntry = z.infer<typeof redisVaultEntrySchema>;\n\n// ============================================\n// Encryption Context\n// ============================================\n\n/**\n * Encryption context for the current request\n * Must be set before performing vault operations\n */\nexport interface EncryptionContext {\n /** Encryption key derived from JWT */\n key: Buffer;\n /** Vault ID (from JWT jti claim) */\n vaultId: string;\n}\n\n/**\n * Module-level AsyncLocalStorage for request-scoped encryption context.\n * This ensures concurrent requests don't interfere with each other's encryption keys.\n */\nconst encryptionContextStorage = new AsyncLocalStorage<EncryptionContext>();\n\n// ============================================\n// Encrypted Redis Vault Implementation\n// ============================================\n\n/**\n * Redis vault with client-side encryption\n *\n * All sensitive data (tokens, credentials, consent, pending auths)\n * is encrypted using a key derived from the client's JWT.\n *\n * Use `runWithContext()` to set encryption context for concurrent safety.\n */\nexport class EncryptedRedisVault implements AuthorizationVault {\n constructor(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly redis: any,\n private readonly encryption: VaultEncryption,\n private readonly namespace = 'vault:',\n ) {}\n\n /**\n * Run a callback with encryption context set for the current async scope.\n * This is the recommended way to set encryption context as it is safe for\n * concurrent requests (each request gets its own isolated context).\n *\n * @param context - Encryption context with key and vaultId\n * @param fn - Async function to run with the context\n * @returns The result of the callback\n *\n * @example\n * ```typescript\n * const result = await vault.runWithContext({ key, vaultId }, async () => {\n * await vault.get(id);\n * await vault.update(id, data);\n * return 'done';\n * });\n * ```\n */\n runWithContext<T>(context: EncryptionContext, fn: () => T | Promise<T>): T | Promise<T> {\n return encryptionContextStorage.run(context, fn);\n }\n\n /**\n * Get current encryption key from AsyncLocalStorage.\n */\n private getKey(): Buffer {\n const asyncContext = encryptionContextStorage.getStore();\n if (asyncContext) {\n return asyncContext.key;\n }\n\n throw new Error('Encryption context not set. Use runWithContext() before performing vault operations.');\n }\n\n /**\n * Create Redis key from vault ID\n */\n private redisKey(id: string): string {\n return `${this.namespace}${id}`;\n }\n\n /**\n * Create credential key from appId and providerId\n */\n private credentialKey(appId: string, providerId: string): string {\n return `${appId}:${providerId}`;\n }\n\n /**\n * Encrypt sensitive data\n */\n private encryptSensitive(data: VaultSensitiveData): EncryptedData {\n return this.encryption.encryptObject(data, this.getKey());\n }\n\n /**\n * Decrypt sensitive data\n */\n private decryptSensitive(encrypted: EncryptedData): VaultSensitiveData {\n return this.encryption.decryptObject<VaultSensitiveData>(encrypted, this.getKey());\n }\n\n /**\n * Convert Redis entry to full vault entry (decrypts sensitive data)\n */\n private toVaultEntry(redisEntry: RedisVaultEntry): AuthorizationVaultEntry {\n const sensitive = this.decryptSensitive(redisEntry.encrypted);\n\n return {\n id: redisEntry.id,\n userSub: redisEntry.userSub,\n userEmail: redisEntry.userEmail,\n userName: redisEntry.userName,\n clientId: redisEntry.clientId,\n createdAt: redisEntry.createdAt,\n lastAccessAt: redisEntry.lastAccessAt,\n appCredentials: sensitive.appCredentials as Record<string, AppCredential>,\n consent: sensitive.consent as VaultConsentRecord | undefined,\n federated: sensitive.federated as VaultFederatedRecord | undefined,\n pendingAuths: sensitive.pendingAuths as PendingIncrementalAuth[],\n authorizedAppIds: redisEntry.authorizedAppIds,\n skippedAppIds: redisEntry.skippedAppIds,\n };\n }\n\n /**\n * Convert vault entry to Redis entry (encrypts sensitive data)\n */\n private toRedisEntry(entry: AuthorizationVaultEntry): RedisVaultEntry {\n const sensitive: VaultSensitiveData = {\n appCredentials: entry.appCredentials,\n consent: entry.consent,\n federated: entry.federated,\n pendingAuths: entry.pendingAuths,\n };\n\n return {\n id: entry.id,\n userSub: entry.userSub,\n userEmail: entry.userEmail,\n userName: entry.userName,\n clientId: entry.clientId,\n createdAt: entry.createdAt,\n lastAccessAt: entry.lastAccessAt,\n authorizedAppIds: entry.authorizedAppIds,\n skippedAppIds: entry.skippedAppIds,\n pendingAuthIds: entry.pendingAuths.map((p) => p.id),\n encrypted: this.encryptSensitive(sensitive),\n };\n }\n\n /**\n * Save entry to Redis\n */\n private async saveEntry(entry: AuthorizationVaultEntry): Promise<void> {\n const redisEntry = this.toRedisEntry(entry);\n await this.redis.set(this.redisKey(entry.id), JSON.stringify(redisEntry));\n }\n\n /**\n * Load entry from Redis\n */\n private async loadEntry(id: string): Promise<AuthorizationVaultEntry | null> {\n const data = await this.redis.get(this.redisKey(id));\n if (!data) return null;\n\n try {\n const redisEntry = redisVaultEntrySchema.parse(JSON.parse(data));\n return this.toVaultEntry(redisEntry);\n } catch (error) {\n // Could be decryption failure (wrong key) or corrupt data\n throw new Error(`Failed to load vault ${id}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n\n // ============================================\n // AuthorizationVault Interface Implementation\n // ============================================\n\n async create(params: {\n userSub: string;\n userEmail?: string;\n userName?: string;\n clientId: string;\n consent?: VaultConsentRecord;\n federated?: VaultFederatedRecord;\n authorizedAppIds?: string[];\n skippedAppIds?: string[];\n }): Promise<AuthorizationVaultEntry> {\n const now = Date.now();\n const entry: AuthorizationVaultEntry = {\n id: randomUUID(),\n userSub: params.userSub,\n userEmail: params.userEmail,\n userName: params.userName,\n clientId: params.clientId,\n createdAt: now,\n lastAccessAt: now,\n appCredentials: {},\n consent: params.consent,\n federated: params.federated,\n pendingAuths: [],\n authorizedAppIds: params.authorizedAppIds ?? [],\n skippedAppIds: params.skippedAppIds ?? [],\n };\n\n await this.saveEntry(entry);\n return entry;\n }\n\n async get(id: string): Promise<AuthorizationVaultEntry | null> {\n const entry = await this.loadEntry(id);\n if (!entry) return null;\n\n // Update last access time\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n\n return entry;\n }\n\n async update(id: string, updates: Partial<AuthorizationVaultEntry>): Promise<void> {\n const entry = await this.loadEntry(id);\n if (!entry) {\n throw new Error(`Vault entry not found: ${id}`);\n }\n\n Object.assign(entry, updates, { lastAccessAt: Date.now() });\n await this.saveEntry(entry);\n }\n\n async delete(id: string): Promise<void> {\n await this.redis.del(this.redisKey(id));\n }\n\n async updateConsent(vaultId: string, consent: VaultConsentRecord): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n entry.consent = consent;\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n\n async authorizeApp(vaultId: string, appId: string): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n entry.skippedAppIds = entry.skippedAppIds.filter((id) => id !== appId);\n if (!entry.authorizedAppIds.includes(appId)) {\n entry.authorizedAppIds.push(appId);\n }\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n\n async createPendingAuth(\n vaultId: string,\n params: {\n appId: string;\n toolId?: string;\n authUrl: string;\n requiredScopes?: string[];\n elicitId?: string;\n ttlMs?: number;\n },\n ): Promise<PendingIncrementalAuth> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) {\n throw new Error(`Vault not found: ${vaultId}`);\n }\n\n const now = Date.now();\n const pendingAuth: PendingIncrementalAuth = {\n id: randomUUID(),\n appId: params.appId,\n toolId: params.toolId,\n authUrl: params.authUrl,\n requiredScopes: params.requiredScopes,\n elicitId: params.elicitId,\n createdAt: now,\n expiresAt: now + (params.ttlMs ?? 10 * 60 * 1000),\n status: 'pending',\n };\n\n entry.pendingAuths.push(pendingAuth);\n entry.lastAccessAt = now;\n await this.saveEntry(entry);\n\n return pendingAuth;\n }\n\n async getPendingAuth(vaultId: string, pendingAuthId: string): Promise<PendingIncrementalAuth | null> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return null;\n\n const pendingAuth = entry.pendingAuths.find((p) => p.id === pendingAuthId);\n if (!pendingAuth) return null;\n\n if (Date.now() > pendingAuth.expiresAt && pendingAuth.status === 'pending') {\n pendingAuth.status = 'expired';\n await this.saveEntry(entry);\n }\n\n return pendingAuth;\n }\n\n async completePendingAuth(vaultId: string, pendingAuthId: string): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n const pendingAuth = entry.pendingAuths.find((p) => p.id === pendingAuthId);\n if (pendingAuth) {\n pendingAuth.status = 'completed';\n\n // Authorize app inline (don't call authorizeApp which reloads entry)\n entry.skippedAppIds = entry.skippedAppIds.filter((id) => id !== pendingAuth.appId);\n if (!entry.authorizedAppIds.includes(pendingAuth.appId)) {\n entry.authorizedAppIds.push(pendingAuth.appId);\n }\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n }\n\n async cancelPendingAuth(vaultId: string, pendingAuthId: string): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n const pendingAuth = entry.pendingAuths.find((p) => p.id === pendingAuthId);\n if (pendingAuth) {\n pendingAuth.status = 'cancelled';\n await this.saveEntry(entry);\n }\n }\n\n async isAppAuthorized(vaultId: string, appId: string): Promise<boolean> {\n // Quick check without decryption - authorizedAppIds is unencrypted\n const data = await this.redis.get(this.redisKey(vaultId));\n if (!data) return false;\n\n try {\n const parsed = JSON.parse(data);\n return Array.isArray(parsed.authorizedAppIds) && parsed.authorizedAppIds.includes(appId);\n } catch {\n return false;\n }\n }\n\n async getPendingAuths(vaultId: string): Promise<PendingIncrementalAuth[]> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return [];\n\n const now = Date.now();\n let updated = false;\n\n const pending = entry.pendingAuths.filter((p) => {\n if (now > p.expiresAt && p.status === 'pending') {\n p.status = 'expired';\n updated = true;\n }\n return p.status === 'pending';\n });\n\n if (updated) {\n await this.saveEntry(entry);\n }\n\n return pending;\n }\n\n // ============================================\n // App Credential Methods\n // ============================================\n\n async addAppCredential(vaultId: string, credential: AppCredential): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n const shouldStore = await this.shouldStoreCredential(vaultId, credential.appId);\n if (!shouldStore) return;\n\n const key = this.credentialKey(credential.appId, credential.providerId);\n entry.appCredentials[key] = credential;\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n\n async removeAppCredential(vaultId: string, appId: string, providerId: string): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n const key = this.credentialKey(appId, providerId);\n delete entry.appCredentials[key];\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n\n async getAppCredentials(vaultId: string, appId: string): Promise<AppCredential[]> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return [];\n\n const prefix = `${appId}:`;\n return Object.entries(entry.appCredentials)\n .filter(([key]) => key.startsWith(prefix))\n .map(([, cred]) => cred);\n }\n\n async getCredential(vaultId: string, appId: string, providerId: string): Promise<AppCredential | null> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return null;\n\n const key = this.credentialKey(appId, providerId);\n return entry.appCredentials[key] ?? null;\n }\n\n async getAllCredentials(vaultId: string, filterByConsent = false): Promise<AppCredential[]> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return [];\n\n const allCredentials = Object.values(entry.appCredentials);\n\n if (!filterByConsent || !entry.consent?.enabled) {\n return allCredentials;\n }\n\n const consentedToolIds = new Set(entry.consent.selectedToolIds);\n return allCredentials.filter((cred) => {\n return Array.from(consentedToolIds).some((toolId) => toolId.startsWith(`${cred.appId}:`));\n });\n }\n\n async updateCredential(\n vaultId: string,\n appId: string,\n providerId: string,\n updates: Partial<Pick<AppCredential, 'lastUsedAt' | 'isValid' | 'invalidReason' | 'expiresAt' | 'metadata'>>,\n ): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n const key = this.credentialKey(appId, providerId);\n const credential = entry.appCredentials[key];\n if (!credential) return;\n\n Object.assign(credential, updates);\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n\n async shouldStoreCredential(vaultId: string, appId: string, toolIds?: string[]): Promise<boolean> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return false;\n\n if (!entry.consent?.enabled) {\n return true;\n }\n\n if (toolIds && toolIds.length > 0) {\n return toolIds.some((toolId) => entry.consent!.selectedToolIds.includes(toolId));\n }\n\n const consentedToolIds = entry.consent.selectedToolIds;\n return consentedToolIds.some((toolId) => toolId.startsWith(`${appId}:`));\n }\n\n async invalidateCredential(vaultId: string, appId: string, providerId: string, reason: string): Promise<void> {\n await this.updateCredential(vaultId, appId, providerId, {\n isValid: false,\n invalidReason: reason,\n });\n }\n\n async refreshOAuthCredential(\n vaultId: string,\n appId: string,\n providerId: string,\n tokens: { accessToken: string; refreshToken?: string; expiresAt?: number },\n ): Promise<void> {\n const entry = await this.loadEntry(vaultId);\n if (!entry) return;\n\n const key = this.credentialKey(appId, providerId);\n const credential = entry.appCredentials[key];\n if (!credential || credential.credential.type !== 'oauth') return;\n\n // Update OAuth tokens\n credential.credential.accessToken = tokens.accessToken;\n if (tokens.refreshToken !== undefined) {\n credential.credential.refreshToken = tokens.refreshToken;\n }\n if (tokens.expiresAt !== undefined) {\n credential.credential.expiresAt = tokens.expiresAt;\n credential.expiresAt = tokens.expiresAt;\n }\n\n credential.isValid = true;\n credential.invalidReason = undefined;\n entry.lastAccessAt = Date.now();\n await this.saveEntry(entry);\n }\n\n async cleanup(): Promise<void> {\n // Redis cleanup would use SCAN to find and clean entries\n // For encrypted vault, this needs careful handling\n // as we can't read data without the encryption key\n }\n}\n\n// ============================================\n// Factory Function\n// ============================================\n\n/**\n * Create an encrypted vault with the given configuration\n */\nexport function createEncryptedVault(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n redis: any,\n config: {\n pepper?: string;\n namespace?: string;\n } = {},\n): { vault: EncryptedRedisVault; encryption: VaultEncryption } {\n const encryption = new VaultEncryption({ pepper: config.pepper });\n const vault = new EncryptedRedisVault(redis, encryption, config.namespace);\n\n return { vault, encryption };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
1
|
+
export * from './transport-session.types';
|
|
2
|
+
export { TransportSessionManager, InMemorySessionStore } from './transport-session.manager';
|
|
3
|
+
export * from './authorization.store';
|
|
4
|
+
export * from './authorization-vault';
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(exports, "
|
|
3
|
+
exports.InMemorySessionStore = exports.TransportSessionManager = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
// Transport session architecture
|
|
6
|
+
tslib_1.__exportStar(require("./transport-session.types"), exports);
|
|
7
|
+
var transport_session_manager_1 = require("./transport-session.manager");
|
|
8
|
+
Object.defineProperty(exports, "TransportSessionManager", { enumerable: true, get: function () { return transport_session_manager_1.TransportSessionManager; } });
|
|
9
|
+
Object.defineProperty(exports, "InMemorySessionStore", { enumerable: true, get: function () { return transport_session_manager_1.InMemorySessionStore; } });
|
|
10
|
+
// Authorization store for OAuth flows
|
|
11
|
+
tslib_1.__exportStar(require("./authorization.store"), exports);
|
|
12
|
+
// Authorization vault for stateful sessions
|
|
13
|
+
tslib_1.__exportStar(require("./authorization-vault"), exports);
|
|
10
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/session/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/session/index.ts"],"names":[],"mappings":";;;;AAAA,iCAAiC;AACjC,oEAA0C;AAC1C,yEAA4F;AAAnF,oIAAA,uBAAuB,OAAA;AAAE,iIAAA,oBAAoB,OAAA;AAEtD,sCAAsC;AACtC,gEAAsC;AAEtC,4CAA4C;AAC5C,gEAAsC","sourcesContent":["// Transport session architecture\nexport * from './transport-session.types';\nexport { TransportSessionManager, InMemorySessionStore } from './transport-session.manager';\n\n// Authorization store for OAuth flows\nexport * from './authorization.store';\n\n// Authorization vault for stateful sessions\nexport * from './authorization-vault';\n"]}
|
|
@@ -2,4 +2,4 @@ import { z } from 'zod';
|
|
|
2
2
|
import { TransparentSession } from './record/session.transparent';
|
|
3
3
|
import { StatefulSession } from './record/session.stateful';
|
|
4
4
|
import { StatelessSession } from './record/session.stateless';
|
|
5
|
-
export declare const SessionSchema: z.ZodUnion<[z.
|
|
5
|
+
export declare const SessionSchema: z.ZodUnion<readonly [z.ZodCustom<TransparentSession, TransparentSession>, z.ZodCustom<StatefulSession, StatefulSession>, z.ZodCustom<StatelessSession, StatelessSession>]>;
|
|
@@ -11,7 +11,7 @@ export declare class SessionService {
|
|
|
11
11
|
* Create and persist a new Session from verified auth data.
|
|
12
12
|
* The returned Session exposes async token helpers, scoped view, and transport JWT helpers.
|
|
13
13
|
*/
|
|
14
|
-
createSession(scope: Scope, args: CreateSessionArgs): Promise<
|
|
14
|
+
createSession(scope: Scope, args: CreateSessionArgs): Promise<TransparentSession | StatefulSession | StatelessSession>;
|
|
15
15
|
private createOrchestratedSession;
|
|
16
16
|
private createTransparentSession;
|
|
17
17
|
}
|