@plitzi/sdk-server 0.32.25 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +326 -162
- package/dist/adapters/authAdapters.d.ts +21 -0
- package/dist/adapters/authAdapters.js +12 -0
- package/dist/adapters/jsonAdapters.d.ts +15 -0
- package/dist/adapters/jsonAdapters.js +9 -4
- package/dist/core/auth/api.d.ts +148 -0
- package/dist/core/auth/api.js +286 -0
- package/dist/core/auth/authorize.d.ts +96 -0
- package/dist/core/auth/authorize.js +92 -0
- package/dist/core/auth/createAuth.d.ts +165 -0
- package/dist/core/auth/createAuth.js +105 -0
- package/dist/core/auth/credentials.d.ts +29 -0
- package/dist/core/auth/credentials.js +48 -0
- package/dist/core/auth/domains.d.ts +41 -0
- package/dist/core/auth/domains.js +78 -0
- package/dist/core/auth/identity.d.ts +108 -0
- package/dist/core/auth/identity.js +164 -0
- package/dist/core/auth/oauth/client.d.ts +5 -0
- package/dist/core/auth/oauth/client.js +47 -0
- package/dist/core/auth/oauth/index.d.ts +78 -0
- package/dist/core/auth/oauth/index.js +113 -0
- package/dist/core/auth/oauth/providers/github.d.ts +2 -0
- package/dist/core/auth/oauth/providers/github.js +48 -0
- package/dist/core/auth/oauth/providers/google.d.ts +2 -0
- package/dist/core/auth/oauth/providers/google.js +30 -0
- package/dist/core/auth/oauth/state.d.ts +23 -0
- package/dist/core/auth/oauth/state.js +55 -0
- package/dist/core/auth/oauth/types.d.ts +51 -0
- package/dist/core/auth/oauth/types.js +13 -0
- package/dist/core/auth/routes.d.ts +50 -0
- package/dist/core/auth/routes.js +129 -0
- package/dist/core/auth/session.d.ts +128 -0
- package/dist/core/auth/session.js +165 -0
- package/dist/core/auth/spaceTokens.d.ts +137 -0
- package/dist/core/auth/spaceTokens.js +212 -0
- package/dist/core/auth/tokens.d.ts +151 -0
- package/dist/core/auth/tokens.js +221 -0
- package/dist/core/createServer.d.ts +29 -0
- package/dist/core/createServer.js +28 -14
- package/dist/core/handlers/authMiddleware.d.ts +27 -0
- package/dist/core/handlers/authMiddleware.js +38 -0
- package/dist/core/handlers/authRouteHandlers.d.ts +46 -0
- package/dist/core/handlers/authRouteHandlers.js +75 -0
- package/dist/core/handlers/types.d.ts +37 -0
- package/dist/{src/core → core}/http/dispatcher.d.ts +2 -2
- package/dist/core/http/dispatcher.js +8 -6
- package/dist/core/http/navigation.d.ts +11 -0
- package/dist/core/http/navigation.js +16 -0
- package/dist/core/http/securityHeaders.js +6 -4
- package/dist/core/http/stages/authApi.d.ts +17 -0
- package/dist/core/http/stages/authApi.js +66 -0
- package/dist/core/http/stages/authRoutes.js +40 -11
- package/dist/core/http/stages/exchangeRoute.d.ts +15 -0
- package/dist/core/http/stages/exchangeRoute.js +67 -0
- package/dist/core/http/stages/health.d.ts +11 -0
- package/dist/core/http/stages/health.js +25 -3
- package/dist/core/http/stages/middlewares.d.ts +2 -0
- package/dist/core/http/stages/static.d.ts +13 -0
- package/dist/core/http/stages/static.js +21 -6
- package/dist/core/http/types.d.ts +35 -0
- package/dist/{modules/mcp/constants.js → core/previewToken.js} +1 -1
- package/dist/core/sdkAssets.d.ts +16 -0
- package/dist/core/sdkAssets.js +46 -0
- package/dist/core/server/baseServer.js +40 -5
- package/dist/core/server/pageServer.d.ts +7 -0
- package/dist/core/server/pageServer.js +13 -17
- package/dist/core/services/action.d.ts +9 -0
- package/dist/core/services/action.js +21 -0
- package/dist/core/services/registry.d.ts +3 -0
- package/dist/core/services/registry.js +9 -19
- package/dist/{src/core → core}/services/resolve.d.ts +1 -0
- package/dist/core/services/resolve.js +6 -4
- package/dist/core/services/rsc.js +3 -2
- package/dist/core/staticFiles.js +1 -1
- package/dist/{src/core → core}/transports.d.ts +3 -0
- package/dist/core/transports.js +7 -6
- package/dist/handlers.d.ts +58 -0
- package/dist/handlers.js +3 -0
- package/dist/{src/helpers → helpers}/buildResponseHelpers.d.ts +2 -1
- package/dist/helpers/buildResponseHelpers.js +13 -4
- package/dist/helpers/buildServerInfo.d.ts +3 -0
- package/dist/helpers/buildServerInfo.js +25 -3
- package/dist/{src/helpers → helpers}/cache/keys.d.ts +5 -1
- package/dist/helpers/cache/keys.js +1 -1
- package/dist/helpers/compress.d.ts +18 -0
- package/dist/helpers/compress.js +47 -11
- package/dist/helpers/offlineDataLoader.d.ts +11 -0
- package/dist/helpers/offlineDataLoader.js +15 -0
- package/dist/helpers/resolveDebugMode.d.ts +10 -0
- package/dist/helpers/resolveDebugMode.js +13 -0
- package/dist/index.d.ts +16 -2
- package/dist/index.js +9 -20
- package/dist/kernel.d.ts +41 -0
- package/dist/kernel.js +22 -0
- package/dist/middlewares/spaceDeployment.d.ts +2 -0
- package/dist/middlewares/spaceDeployment.js +2 -1
- package/dist/modules/actions/handler.d.ts +11 -0
- package/dist/modules/actions/handler.js +77 -0
- package/dist/modules/connectors/engine.d.ts +42 -0
- package/dist/modules/connectors/engine.js +221 -0
- package/dist/modules/connectors/getByPath.d.ts +8 -0
- package/dist/modules/connectors/getByPath.js +21 -0
- package/dist/modules/connectors/index.d.ts +7 -0
- package/dist/modules/connectors/projection.d.ts +18 -0
- package/dist/modules/connectors/projection.js +108 -0
- package/dist/modules/connectors/resolver.d.ts +18 -0
- package/dist/modules/connectors/resolver.js +68 -0
- package/dist/modules/connectors/types.d.ts +19 -0
- package/dist/{src/modules → modules}/rsc/handler.d.ts +2 -2
- package/dist/modules/rsc/handler.js +54 -2
- package/dist/modules/rsc/resolveRscData.d.ts +35 -0
- package/dist/modules/rsc/resolveRscData.js +74 -0
- package/dist/{src/modules → modules}/ssr/Component.d.ts +4 -1
- package/dist/modules/ssr/Component.js +10 -3
- package/dist/modules/ssr/buildBody.d.ts +9 -0
- package/dist/modules/ssr/handler.d.ts +4 -0
- package/dist/modules/ssr/handler.js +18 -1
- package/dist/{src/modules → modules}/ssr/loadPluginComponents.d.ts +5 -2
- package/dist/modules/ssr/loadPluginComponents.js +20 -2
- package/dist/{src/modules → modules}/ssr/prepareRender.d.ts +2 -2
- package/dist/modules/ssr/prepareRender.js +24 -7
- package/dist/modules/ssr/preview.d.ts +10 -0
- package/dist/modules/ssr/preview.js +5 -78
- package/dist/modules/ssr/registerExternalPlugins.js +1 -1
- package/dist/modules/ssr/streamBody.d.ts +5 -0
- package/dist/modules/ssr/streamBody.js +1 -1
- package/dist/modules/ssr/template.d.ts +2 -0
- package/dist/modules/ssr/template.js +1 -1
- package/dist/plugins/compile.js +1 -1
- package/dist/plugins/manager.js +12 -8
- package/dist/ssr.d.ts +15 -0
- package/dist/ssr.js +4 -0
- package/package.json +29 -25
- package/dist/.gitkeep +0 -0
- package/dist/core/server/mcpServer.js +0 -29
- package/dist/core/services/mcp.js +0 -27
- package/dist/core/services/oauth.js +0 -116
- package/dist/core/services/preview.js +0 -37
- package/dist/core/services/proxy.js +0 -12
- package/dist/mcp.d.ts +0 -2
- package/dist/mcp.js +0 -7
- package/dist/modules/ai/AIEngine.js +0 -120
- package/dist/modules/ai/toolkit.js +0 -59
- package/dist/modules/mcp/apps/example/view/index.tsx +0 -70
- package/dist/modules/mcp/apps/index.js +0 -16
- package/dist/modules/mcp/apps/render/index.js +0 -17
- package/dist/modules/mcp/apps/render/styles.js +0 -54
- package/dist/modules/mcp/apps/render/view/heldBatch.ts +0 -107
- package/dist/modules/mcp/apps/render/view/index.tsx +0 -314
- package/dist/modules/mcp/apps/render/view/streamProgress.ts +0 -137
- package/dist/modules/mcp/apps/shared/assets.js +0 -10
- package/dist/modules/mcp/apps/shared/bundle.js +0 -23
- package/dist/modules/mcp/apps/shared/page.js +0 -34
- package/dist/modules/mcp/apps/shared/registerApp.js +0 -43
- package/dist/modules/mcp/apps/shared/resolve.js +0 -5
- package/dist/modules/mcp/apps/shared/shell.ejs +0 -59
- package/dist/modules/mcp/apps/shared/zodEnglishOnly.js +0 -23
- package/dist/modules/mcp/catalogs/builtinCallbacks.js +0 -204
- package/dist/modules/mcp/catalogs/builtinComponents.js +0 -170
- package/dist/modules/mcp/catalogs/builtinElementCallbacks.js +0 -50
- package/dist/modules/mcp/catalogs/builtinTransformers.js +0 -148
- package/dist/modules/mcp/catalogs/builtinUtilities.js +0 -90
- package/dist/modules/mcp/catalogs/cssCatalog/border.js +0 -30
- package/dist/modules/mcp/catalogs/cssCatalog/box.js +0 -31
- package/dist/modules/mcp/catalogs/cssCatalog/helpers.js +0 -185
- package/dist/modules/mcp/catalogs/cssCatalog/index.js +0 -131
- package/dist/modules/mcp/catalogs/cssCatalog/layout.js +0 -98
- package/dist/modules/mcp/catalogs/cssCatalog/visual.js +0 -144
- package/dist/modules/mcp/catalogs/observed.js +0 -90
- package/dist/modules/mcp/catalogs/paramSpec.js +0 -69
- package/dist/modules/mcp/catalogs/registry.js +0 -89
- package/dist/modules/mcp/handler.js +0 -83
- package/dist/modules/mcp/helpers/agentPrompt.js +0 -104
- package/dist/modules/mcp/helpers/computeVersion.js +0 -16
- package/dist/modules/mcp/helpers/guide.js +0 -467
- package/dist/modules/mcp/helpers/interactions.js +0 -123
- package/dist/modules/mcp/helpers/log.js +0 -64
- package/dist/modules/mcp/helpers/opResult.js +0 -18
- package/dist/modules/mcp/helpers/space.js +0 -300
- package/dist/modules/mcp/helpers/uris.js +0 -44
- package/dist/modules/mcp/previewClient.js +0 -31
- package/dist/modules/mcp/proxy/config.js +0 -63
- package/dist/modules/mcp/proxy/fetch.js +0 -91
- package/dist/modules/mcp/proxy/grant.js +0 -67
- package/dist/modules/mcp/proxy/guard.js +0 -38
- package/dist/modules/mcp/proxy/handler.js +0 -99
- package/dist/modules/mcp/proxy/payload.js +0 -29
- package/dist/modules/mcp/proxy/rewrite.js +0 -138
- package/dist/modules/mcp/proxy/sign.js +0 -15
- package/dist/modules/mcp/proxy/types.js +0 -9
- package/dist/modules/mcp/resources/canonical.js +0 -30
- package/dist/modules/mcp/resources/core.js +0 -18
- package/dist/modules/mcp/resources/envelope.js +0 -14
- package/dist/modules/mcp/resources/primer.js +0 -31
- package/dist/modules/mcp/resources/register.js +0 -190
- package/dist/modules/mcp/resources/renderGuide.js +0 -451
- package/dist/modules/mcp/resources/router.js +0 -37
- package/dist/modules/mcp/resources/schema.js +0 -43
- package/dist/modules/mcp/resources/style.js +0 -34
- package/dist/modules/mcp/screenshotClient.js +0 -47
- package/dist/modules/mcp/server.js +0 -113
- package/dist/modules/mcp/tools/apply/dispatch.js +0 -105
- package/dist/modules/mcp/tools/apply/index.js +0 -150
- package/dist/modules/mcp/tools/apply/writeResult.js +0 -37
- package/dist/modules/mcp/tools/index.js +0 -24
- package/dist/modules/mcp/tools/operations/index.js +0 -45
- package/dist/modules/mcp/tools/operations/schema/bindings/deleteBinding.js +0 -32
- package/dist/modules/mcp/tools/operations/schema/bindings/patchBinding.js +0 -36
- package/dist/modules/mcp/tools/operations/schema/bindings/upsertBinding.js +0 -47
- package/dist/modules/mcp/tools/operations/schema/elements/deleteElement.js +0 -29
- package/dist/modules/mcp/tools/operations/schema/elements/moveElement.js +0 -41
- package/dist/modules/mcp/tools/operations/schema/elements/patchElement.js +0 -58
- package/dist/modules/mcp/tools/operations/schema/elements/repeatElement.js +0 -148
- package/dist/modules/mcp/tools/operations/schema/elements/upsertElement.js +0 -65
- package/dist/modules/mcp/tools/operations/schema/folders/deleteFolder.js +0 -30
- package/dist/modules/mcp/tools/operations/schema/folders/upsertFolder.js +0 -49
- package/dist/modules/mcp/tools/operations/schema/interactions/deleteInteraction.js +0 -52
- package/dist/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.js +0 -47
- package/dist/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.js +0 -44
- package/dist/modules/mcp/tools/operations/schema/operations.js +0 -41
- package/dist/modules/mcp/tools/operations/schema/pages/deletePage.js +0 -25
- package/dist/modules/mcp/tools/operations/schema/pages/upsertPage.js +0 -75
- package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.js +0 -45
- package/dist/modules/mcp/tools/operations/schema/shared.js +0 -122
- package/dist/modules/mcp/tools/operations/schema/translator.js +0 -215
- package/dist/modules/mcp/tools/operations/schema/variables/deleteVariable.js +0 -18
- package/dist/modules/mcp/tools/operations/schema/variables/upsertVariable.js +0 -42
- package/dist/modules/mcp/tools/operations/schema/write.js +0 -109
- package/dist/modules/mcp/tools/operations/schemaIds.js +0 -54
- package/dist/modules/mcp/tools/operations/style/definitions/deleteDefinition.js +0 -21
- package/dist/modules/mcp/tools/operations/style/definitions/patchDefinition.js +0 -28
- package/dist/modules/mcp/tools/operations/style/definitions/upsertDefinition.js +0 -24
- package/dist/modules/mcp/tools/operations/style/definitions/upsertDefinitions.js +0 -40
- package/dist/modules/mcp/tools/operations/style/globalStyles/deleteGlobalStyle.js +0 -21
- package/dist/modules/mcp/tools/operations/style/globalStyles/patchGlobalStyle.js +0 -28
- package/dist/modules/mcp/tools/operations/style/globalStyles/upsertGlobalStyle.js +0 -24
- package/dist/modules/mcp/tools/operations/style/idStyles/deleteIdStyle.js +0 -21
- package/dist/modules/mcp/tools/operations/style/idStyles/patchIdStyle.js +0 -28
- package/dist/modules/mcp/tools/operations/style/idStyles/upsertIdStyle.js +0 -24
- package/dist/modules/mcp/tools/operations/style/operations.js +0 -29
- package/dist/modules/mcp/tools/operations/style/shared.js +0 -59
- package/dist/modules/mcp/tools/operations/style/translator.js +0 -101
- package/dist/modules/mcp/tools/operations/style/variables/deleteStyleVariable.js +0 -21
- package/dist/modules/mcp/tools/operations/style/variables/upsertStyleVariable.js +0 -22
- package/dist/modules/mcp/tools/operations/style/write.js +0 -108
- package/dist/modules/mcp/tools/preview.js +0 -37
- package/dist/modules/mcp/tools/read.js +0 -51
- package/dist/modules/mcp/tools/render.js +0 -184
- package/dist/modules/mcp/tools/screenshot.js +0 -83
- package/dist/modules/mcp/tools/search.js +0 -115
- package/dist/modules/mcp/tools/shared/expandOperations.js +0 -44
- package/dist/modules/mcp/tools/shared/tool.js +0 -33
- package/dist/modules/mcp/tools/shared/validator/audit.js +0 -124
- package/dist/modules/mcp/tools/shared/validator/batch.js +0 -39
- package/dist/modules/mcp/tools/shared/validator/bindings.js +0 -70
- package/dist/modules/mcp/tools/shared/validator/context.js +0 -35
- package/dist/modules/mcp/tools/shared/validator/css.js +0 -39
- package/dist/modules/mcp/tools/shared/validator/elements.js +0 -68
- package/dist/modules/mcp/tools/shared/validator/index.js +0 -246
- package/dist/modules/mcp/tools/shared/validator/interactions.js +0 -103
- package/dist/modules/mcp/tools/shared/validator/refs.js +0 -28
- package/dist/modules/mcp/tools/validate.js +0 -47
- package/dist/modules/oauth/authorize.js +0 -177
- package/dist/modules/oauth/challenge.js +0 -33
- package/dist/modules/oauth/consentPage.js +0 -118
- package/dist/modules/oauth/metadata.js +0 -69
- package/dist/modules/oauth/params.js +0 -5
- package/dist/modules/oauth/pkce.js +0 -15
- package/dist/modules/oauth/records.js +0 -46
- package/dist/modules/oauth/register.js +0 -55
- package/dist/modules/oauth/respond.js +0 -44
- package/dist/modules/oauth/token.js +0 -100
- package/dist/public/.gitkeep +0 -0
- package/dist/src/adapters/jsonAdapters.d.ts +0 -7
- package/dist/src/core/createServer.d.ts +0 -14
- package/dist/src/core/http/stages/health.d.ts +0 -2
- package/dist/src/core/http/stages/middlewares.d.ts +0 -2
- package/dist/src/core/http/stages/static.d.ts +0 -5
- package/dist/src/core/http/types.d.ts +0 -22
- package/dist/src/core/server/mcpServer.d.ts +0 -2
- package/dist/src/core/server/pageServer.d.ts +0 -10
- package/dist/src/core/services/mcp.d.ts +0 -3
- package/dist/src/core/services/oauth.d.ts +0 -18
- package/dist/src/core/services/preview.d.ts +0 -2
- package/dist/src/core/services/proxy.d.ts +0 -2
- package/dist/src/core/services/registry.d.ts +0 -4
- package/dist/src/helpers/buildServerInfo.d.ts +0 -2
- package/dist/src/helpers/compress.d.ts +0 -3
- package/dist/src/index.d.ts +0 -15
- package/dist/src/mcp.d.ts +0 -14
- package/dist/src/middlewares/spaceDeployment.d.ts +0 -2
- package/dist/src/modules/ai/AIEngine.d.ts +0 -20
- package/dist/src/modules/ai/index.d.ts +0 -4
- package/dist/src/modules/ai/toolkit.d.ts +0 -17
- package/dist/src/modules/mcp/apps/example/index.d.ts +0 -8
- package/dist/src/modules/mcp/apps/index.d.ts +0 -11
- package/dist/src/modules/mcp/apps/render/index.d.ts +0 -4
- package/dist/src/modules/mcp/apps/render/styles.d.ts +0 -10
- package/dist/src/modules/mcp/apps/shared/assets.d.ts +0 -10
- package/dist/src/modules/mcp/apps/shared/bundle.d.ts +0 -4
- package/dist/src/modules/mcp/apps/shared/index.d.ts +0 -3
- package/dist/src/modules/mcp/apps/shared/page.d.ts +0 -2
- package/dist/src/modules/mcp/apps/shared/registerApp.d.ts +0 -5
- package/dist/src/modules/mcp/apps/shared/resolve.d.ts +0 -1
- package/dist/src/modules/mcp/apps/shared/zodEnglishOnly.d.ts +0 -4
- package/dist/src/modules/mcp/catalogs/builtinCallbacks.d.ts +0 -23
- package/dist/src/modules/mcp/catalogs/builtinComponents.d.ts +0 -4
- package/dist/src/modules/mcp/catalogs/builtinElementCallbacks.d.ts +0 -20
- package/dist/src/modules/mcp/catalogs/builtinTransformers.d.ts +0 -28
- package/dist/src/modules/mcp/catalogs/builtinUtilities.d.ts +0 -18
- package/dist/src/modules/mcp/catalogs/cssCatalog/border.d.ts +0 -4
- package/dist/src/modules/mcp/catalogs/cssCatalog/box.d.ts +0 -4
- package/dist/src/modules/mcp/catalogs/cssCatalog/helpers.d.ts +0 -34
- package/dist/src/modules/mcp/catalogs/cssCatalog/index.d.ts +0 -19
- package/dist/src/modules/mcp/catalogs/cssCatalog/layout.d.ts +0 -9
- package/dist/src/modules/mcp/catalogs/cssCatalog/visual.d.ts +0 -8
- package/dist/src/modules/mcp/catalogs/index.d.ts +0 -9
- package/dist/src/modules/mcp/catalogs/observed.d.ts +0 -48
- package/dist/src/modules/mcp/catalogs/paramSpec.d.ts +0 -42
- package/dist/src/modules/mcp/catalogs/registry.d.ts +0 -35
- package/dist/src/modules/mcp/e2e/index.d.ts +0 -6
- package/dist/src/modules/mcp/e2e/mcpEndpoint.d.ts +0 -27
- package/dist/src/modules/mcp/e2e/postMessageChannel.d.ts +0 -22
- package/dist/src/modules/mcp/e2e/renderingHost.d.ts +0 -34
- package/dist/src/modules/mcp/handler.d.ts +0 -22
- package/dist/src/modules/mcp/helpers/agentPrompt.d.ts +0 -4
- package/dist/src/modules/mcp/helpers/computeVersion.d.ts +0 -1
- package/dist/src/modules/mcp/helpers/guide.d.ts +0 -4
- package/dist/src/modules/mcp/helpers/index.d.ts +0 -8
- package/dist/src/modules/mcp/helpers/interactions.d.ts +0 -30
- package/dist/src/modules/mcp/helpers/log.d.ts +0 -8
- package/dist/src/modules/mcp/helpers/opResult.d.ts +0 -13
- package/dist/src/modules/mcp/helpers/space.d.ts +0 -115
- package/dist/src/modules/mcp/helpers/uris.d.ts +0 -28
- package/dist/src/modules/mcp/index.d.ts +0 -13
- package/dist/src/modules/mcp/previewClient.d.ts +0 -13
- package/dist/src/modules/mcp/proxy/config.d.ts +0 -19
- package/dist/src/modules/mcp/proxy/fetch.d.ts +0 -18
- package/dist/src/modules/mcp/proxy/grant.d.ts +0 -25
- package/dist/src/modules/mcp/proxy/guard.d.ts +0 -6
- package/dist/src/modules/mcp/proxy/handler.d.ts +0 -8
- package/dist/src/modules/mcp/proxy/index.d.ts +0 -8
- package/dist/src/modules/mcp/proxy/payload.d.ts +0 -8
- package/dist/src/modules/mcp/proxy/rewrite.d.ts +0 -18
- package/dist/src/modules/mcp/proxy/sign.d.ts +0 -6
- package/dist/src/modules/mcp/proxy/types.d.ts +0 -45
- package/dist/src/modules/mcp/resources/canonical.d.ts +0 -6
- package/dist/src/modules/mcp/resources/core.d.ts +0 -5
- package/dist/src/modules/mcp/resources/envelope.d.ts +0 -10
- package/dist/src/modules/mcp/resources/index.d.ts +0 -8
- package/dist/src/modules/mcp/resources/primer.d.ts +0 -7
- package/dist/src/modules/mcp/resources/register.d.ts +0 -10
- package/dist/src/modules/mcp/resources/renderGuide.d.ts +0 -10
- package/dist/src/modules/mcp/resources/router.d.ts +0 -10
- package/dist/src/modules/mcp/resources/schema.d.ts +0 -5
- package/dist/src/modules/mcp/resources/style.d.ts +0 -5
- package/dist/src/modules/mcp/screenshotClient.d.ts +0 -13
- package/dist/src/modules/mcp/server.d.ts +0 -31
- package/dist/src/modules/mcp/tests/helpers.d.ts +0 -13
- package/dist/src/modules/mcp/tools/apply/dispatch.d.ts +0 -6
- package/dist/src/modules/mcp/tools/apply/index.d.ts +0 -470
- package/dist/src/modules/mcp/tools/apply/writeResult.d.ts +0 -8
- package/dist/src/modules/mcp/tools/index.d.ts +0 -18
- package/dist/src/modules/mcp/tools/operations/index.d.ts +0 -928
- package/dist/src/modules/mcp/tools/operations/schema/bindings/deleteBinding.d.ts +0 -17
- package/dist/src/modules/mcp/tools/operations/schema/bindings/patchBinding.d.ts +0 -25
- package/dist/src/modules/mcp/tools/operations/schema/bindings/upsertBinding.d.ts +0 -27
- package/dist/src/modules/mcp/tools/operations/schema/elements/deleteElement.d.ts +0 -10
- package/dist/src/modules/mcp/tools/operations/schema/elements/moveElement.d.ts +0 -16
- package/dist/src/modules/mcp/tools/operations/schema/elements/patchElement.d.ts +0 -22
- package/dist/src/modules/mcp/tools/operations/schema/elements/repeatElement.d.ts +0 -55
- package/dist/src/modules/mcp/tools/operations/schema/elements/upsertElement.d.ts +0 -16
- package/dist/src/modules/mcp/tools/operations/schema/folders/deleteFolder.d.ts +0 -9
- package/dist/src/modules/mcp/tools/operations/schema/folders/upsertFolder.d.ts +0 -12
- package/dist/src/modules/mcp/tools/operations/schema/index.d.ts +0 -21
- package/dist/src/modules/mcp/tools/operations/schema/interactions/deleteInteraction.d.ts +0 -12
- package/dist/src/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.d.ts +0 -18
- package/dist/src/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.d.ts +0 -27
- package/dist/src/modules/mcp/tools/operations/schema/operations.d.ts +0 -229
- package/dist/src/modules/mcp/tools/operations/schema/pages/deletePage.d.ts +0 -9
- package/dist/src/modules/mcp/tools/operations/schema/pages/upsertPage.d.ts +0 -14
- package/dist/src/modules/mcp/tools/operations/schema/settings/patchSettings.d.ts +0 -34
- package/dist/src/modules/mcp/tools/operations/schema/shared.d.ts +0 -92
- package/dist/src/modules/mcp/tools/operations/schema/translator.d.ts +0 -12
- package/dist/src/modules/mcp/tools/operations/schema/variables/deleteVariable.d.ts +0 -9
- package/dist/src/modules/mcp/tools/operations/schema/variables/upsertVariable.d.ts +0 -16
- package/dist/src/modules/mcp/tools/operations/schema/write.d.ts +0 -42
- package/dist/src/modules/mcp/tools/operations/schemaIds.d.ts +0 -6
- package/dist/src/modules/mcp/tools/operations/style/definitions/deleteDefinition.d.ts +0 -9
- package/dist/src/modules/mcp/tools/operations/style/definitions/patchDefinition.d.ts +0 -37
- package/dist/src/modules/mcp/tools/operations/style/definitions/upsertDefinition.d.ts +0 -37
- package/dist/src/modules/mcp/tools/operations/style/definitions/upsertDefinitions.d.ts +0 -41
- package/dist/src/modules/mcp/tools/operations/style/globalStyles/deleteGlobalStyle.d.ts +0 -9
- package/dist/src/modules/mcp/tools/operations/style/globalStyles/patchGlobalStyle.d.ts +0 -37
- package/dist/src/modules/mcp/tools/operations/style/globalStyles/upsertGlobalStyle.d.ts +0 -37
- package/dist/src/modules/mcp/tools/operations/style/idStyles/deleteIdStyle.d.ts +0 -9
- package/dist/src/modules/mcp/tools/operations/style/idStyles/patchIdStyle.d.ts +0 -37
- package/dist/src/modules/mcp/tools/operations/style/idStyles/upsertIdStyle.d.ts +0 -37
- package/dist/src/modules/mcp/tools/operations/style/index.d.ts +0 -15
- package/dist/src/modules/mcp/tools/operations/style/operations.d.ts +0 -264
- package/dist/src/modules/mcp/tools/operations/style/shared.d.ts +0 -116
- package/dist/src/modules/mcp/tools/operations/style/translator.d.ts +0 -12
- package/dist/src/modules/mcp/tools/operations/style/variables/deleteStyleVariable.d.ts +0 -15
- package/dist/src/modules/mcp/tools/operations/style/variables/upsertStyleVariable.d.ts +0 -20
- package/dist/src/modules/mcp/tools/operations/style/write.d.ts +0 -12
- package/dist/src/modules/mcp/tools/preview.d.ts +0 -465
- package/dist/src/modules/mcp/tools/read.d.ts +0 -9
- package/dist/src/modules/mcp/tools/render.d.ts +0 -499
- package/dist/src/modules/mcp/tools/render.test.d.ts +0 -1
- package/dist/src/modules/mcp/tools/screenshot.d.ts +0 -470
- package/dist/src/modules/mcp/tools/search.d.ts +0 -15
- package/dist/src/modules/mcp/tools/shared/expandOperations.d.ts +0 -13
- package/dist/src/modules/mcp/tools/shared/tool.d.ts +0 -72
- package/dist/src/modules/mcp/tools/shared/validator/audit.d.ts +0 -4
- package/dist/src/modules/mcp/tools/shared/validator/batch.d.ts +0 -5
- package/dist/src/modules/mcp/tools/shared/validator/bindings.d.ts +0 -6
- package/dist/src/modules/mcp/tools/shared/validator/context.d.ts +0 -38
- package/dist/src/modules/mcp/tools/shared/validator/css.d.ts +0 -4
- package/dist/src/modules/mcp/tools/shared/validator/elements.d.ts +0 -7
- package/dist/src/modules/mcp/tools/shared/validator/index.d.ts +0 -8
- package/dist/src/modules/mcp/tools/shared/validator/interactions.d.ts +0 -3
- package/dist/src/modules/mcp/tools/shared/validator/refs.d.ts +0 -4
- package/dist/src/modules/mcp/tools/validate.d.ts +0 -467
- package/dist/src/modules/mcp/types/aiSchema.d.ts +0 -218
- package/dist/src/modules/mcp/types/appTypes.d.ts +0 -26
- package/dist/src/modules/mcp/types/index.d.ts +0 -5
- package/dist/src/modules/mcp/types/previewTypes.d.ts +0 -25
- package/dist/src/modules/mcp/types/screenshotTypes.d.ts +0 -29
- package/dist/src/modules/mcp/types/toolTypes.d.ts +0 -138
- package/dist/src/modules/oauth/authorize.d.ts +0 -7
- package/dist/src/modules/oauth/challenge.d.ts +0 -11
- package/dist/src/modules/oauth/consentPage.d.ts +0 -7
- package/dist/src/modules/oauth/metadata.d.ts +0 -40
- package/dist/src/modules/oauth/params.d.ts +0 -5
- package/dist/src/modules/oauth/pkce.d.ts +0 -6
- package/dist/src/modules/oauth/records.d.ts +0 -71
- package/dist/src/modules/oauth/register.d.ts +0 -5
- package/dist/src/modules/oauth/respond.d.ts +0 -13
- package/dist/src/modules/oauth/token.d.ts +0 -5
- package/dist/src/modules/ssr/buildBody.d.ts +0 -9
- package/dist/src/modules/ssr/handler.d.ts +0 -4
- package/dist/src/modules/ssr/preview.d.ts +0 -16
- package/dist/src/modules/ssr/streamBody.d.ts +0 -5
- package/dist/src/modules/ssr/template.d.ts +0 -6
- package/dist/src/standalone/alias-loader.d.mts +0 -2
- package/dist/src/standalone/plugins/ClientInfo.d.ts +0 -2
- package/dist/src/standalone/plugins/ServerInfo.d.ts +0 -2
- package/dist/src/standalone/plugins/SharedInfo.d.ts +0 -2
- package/dist/src/standalone/plugins/styles.d.ts +0 -5
- package/dist/src/standalone/register-alias.d.mts +0 -1
- package/dist/src/standalone/server.d.ts +0 -1
- package/dist/src/standalone/stubs/react-syntax-highlighter.d.mts +0 -31
- package/skills/plitzi-render/SKILL.md +0 -174
- /package/dist/{src/core/http/dispatcher.test.d.ts → core/auth/api.test.d.ts} +0 -0
- /package/dist/{src/core/server/mcpServer.test.d.ts → core/auth/authorize.test.d.ts} +0 -0
- /package/dist/{src/modules/ai/toolkit.test.d.ts → core/auth/createAuth.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/apps/apps.test.d.ts → core/auth/domains.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/apps/render/styles.test.d.ts → core/auth/identity.test.d.ts} +0 -0
- /package/dist/{src/modules → core/auth}/oauth/oauth.test.d.ts +0 -0
- /package/dist/{src/modules/mcp/catalogs/builtinTransformers.test.d.ts → core/auth/routes.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/catalogs/cssCatalog/cssCatalog.test.d.ts → core/auth/session.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/e2e/connector.test.d.ts → core/auth/spaceTokens.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/e2e/host.test.d.ts → core/auth/tokens.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/e2e/oauthConnector.test.d.ts → core/createServer.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/helpers/log.test.d.ts → core/handlers/handlers.test.d.ts} +0 -0
- /package/dist/{src/core → core}/health.d.ts +0 -0
- /package/dist/{src/modules/mcp/mcp.bench.d.ts → core/http/dispatcher.test.d.ts} +0 -0
- /package/dist/{src/core → core}/http/securityHeaders.d.ts +0 -0
- /package/dist/{src/core → core}/http/stages/authRoutes.d.ts +0 -0
- /package/dist/{src/core → core}/http/stages/pluginAssets.d.ts +0 -0
- /package/dist/{src/core → core}/mimeTypes.d.ts +0 -0
- /package/dist/{src/modules/mcp/constants.d.ts → core/previewToken.d.ts} +0 -0
- /package/dist/{src/core → core}/requestParser.d.ts +0 -0
- /package/dist/{src/core → core}/server/baseServer.d.ts +0 -0
- /package/dist/{src/modules/mcp/proxy/endpoint.test.d.ts → core/server/baseServer.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/proxy/proxy.test.d.ts → core/services/resolve.test.d.ts} +0 -0
- /package/dist/{src/core → core}/services/rsc.d.ts +0 -0
- /package/dist/{src/core → core}/services/ssr.d.ts +0 -0
- /package/dist/{src/core → core}/staticFiles.d.ts +0 -0
- /package/dist/{src/modules/mcp/proxy/wiring.test.d.ts → helpers/buildResponseHelpers.test.d.ts} +0 -0
- /package/dist/{src/helpers → helpers}/cache/TtlCache.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/cache/cacheManager.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/cache/defaults.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/cache/index.d.ts +0 -0
- /package/dist/{src/modules/mcp/tests/apply.test.d.ts → helpers/cache/keys.test.d.ts} +0 -0
- /package/dist/{src/helpers → helpers}/cache/serverCaches.d.ts +0 -0
- /package/dist/{src/modules/mcp/tests/bindings.test.d.ts → helpers/compress.test.d.ts} +0 -0
- /package/dist/{src/helpers → helpers}/escapeJson.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/metrics.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/normalizePlugins.d.ts +0 -0
- /package/dist/{src/modules/mcp/tests/css.test.d.ts → helpers/offlineDataLoader.test.d.ts} +0 -0
- /package/dist/{src/helpers → helpers}/readCookie.d.ts +0 -0
- /package/dist/{src/modules/mcp/tests/interactions.test.d.ts → helpers/resolveDebugMode.test.d.ts} +0 -0
- /package/dist/{src/helpers → helpers}/runMiddlewares.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/serverLog.d.ts +0 -0
- /package/dist/{src/middlewares → middlewares}/auth.d.ts +0 -0
- /package/dist/{src/middlewares → middlewares}/basicAuth.d.ts +0 -0
- /package/dist/{src/modules/mcp/tests/pages.test.d.ts → middlewares/spaceDeployment.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/tests/reads.test.d.ts → modules/actions/handler.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/tests/schemaIds.test.d.ts → modules/connectors/engine.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/tests/search.test.d.ts → modules/connectors/projection.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/tests/skill.test.d.ts → modules/connectors/resolver.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/tests/styles.test.d.ts → modules/rsc/resolveRscData.test.d.ts} +0 -0
- /package/dist/{src/modules → modules}/ssr/applySSRResult.d.ts +0 -0
- /package/dist/{src/modules/mcp/tests/tools.test.d.ts → modules/ssr/loadPluginComponents.test.d.ts} +0 -0
- /package/dist/{src/modules/mcp/tests/validation.test.d.ts → modules/ssr/metering.test.d.ts} +0 -0
- /package/dist/{src/modules → modules}/ssr/registerExternalPlugins.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/compile.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/copy.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/detect.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/manager.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/validate.d.ts +0 -0
- /package/dist/{src/plugins → plugins}/validate.test.d.ts +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SSRAdapters, SSRRequest, SSRSession, SSRUser } from '@plitzi/sdk-shared';
|
|
2
|
+
/**
|
|
3
|
+
* The three adapters a page server asks about WHO a request carries, for a deployment that answers them itself.
|
|
4
|
+
*
|
|
5
|
+
* Separate from the space adapters on purpose: what a request renders and who is looking at it are two different
|
|
6
|
+
* integrations, and a deployment routinely swaps one without touching the other. Composing them is a spread.
|
|
7
|
+
*
|
|
8
|
+
* A deployment running the auth kernel does not need this at all — `createAuth(...).ssrAdapters` answers the same
|
|
9
|
+
* three, from the flows that mint and revoke the sessions. This is for the case with no kernel: a fixed user in a
|
|
10
|
+
* test, a proxy that has already authenticated the request, or a store reached directly.
|
|
11
|
+
*/
|
|
12
|
+
export type AuthAdaptersConfig = {
|
|
13
|
+
/** Who this request carries. A value for every request, or a function that reads the credential off one. */
|
|
14
|
+
user?: SSRUser | ((req: SSRRequest) => SSRUser | undefined | Promise<SSRUser | undefined>);
|
|
15
|
+
/** Verify credentials and mint a session. Return undefined to refuse; never throw for a wrong password. */
|
|
16
|
+
authenticate?: (credentials: Record<string, string>, req: SSRRequest) => Promise<SSRSession | undefined>;
|
|
17
|
+
/** Revoke the session this request carries, at the source. The cookies are the server's to clear. */
|
|
18
|
+
endSession?: (req: SSRRequest) => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
export type AuthAdapters = Pick<SSRAdapters, 'getUser' | 'authenticate' | 'endSession'>;
|
|
21
|
+
export declare const createAuthAdapters: (config: AuthAdaptersConfig) => AuthAdapters;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/adapters/authAdapters.ts
|
|
2
|
+
var createAuthAdapters = (config) => {
|
|
3
|
+
const { user, authenticate, endSession } = config;
|
|
4
|
+
const getUser = user ? (req) => Promise.resolve(typeof user === "function" ? user(req) : user) : void 0;
|
|
5
|
+
return {
|
|
6
|
+
...getUser ? { getUser } : {},
|
|
7
|
+
...authenticate ? { authenticate } : {},
|
|
8
|
+
...endSession ? { endSession } : {}
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { createAuthAdapters };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { OfflineDataRaw, SSRPageAdapters, SSRSpaceDeployment } from '@plitzi/sdk-shared';
|
|
2
|
+
/**
|
|
3
|
+
* Where a space comes from, and nothing else. Who is looking at it is `createAuthAdapters` (or the auth kernel's
|
|
4
|
+
* own `ssrAdapters`) — a deployment composes the two with a spread, and swaps either without disturbing the other.
|
|
5
|
+
*/
|
|
6
|
+
export type JsonAdaptersConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* The space: a path to a `{ schema, style }` JSON, a function returning one per request, or the data itself for a
|
|
9
|
+
* consumer that already holds it (composed at startup, fetched once, built in a test). Only a path can be written
|
|
10
|
+
* back to, so `saveOfflineData` is offered only when one was given.
|
|
11
|
+
*/
|
|
12
|
+
offlineData: OfflineDataRaw | string | ((spaceId: number, environment: string, revision?: number) => string);
|
|
13
|
+
deployment?: string | SSRSpaceDeployment | Record<string, SSRSpaceDeployment>;
|
|
14
|
+
};
|
|
15
|
+
export declare const createJsonAdapters: (config: JsonAdaptersConfig) => SSRPageAdapters;
|
|
@@ -3,9 +3,14 @@ import { readFileSync, writeFileSync } from "node:fs";
|
|
|
3
3
|
var isDeploymentObject = (v) => typeof v === "object" && ("spaceId" in v || "environment" in v || "error" in v);
|
|
4
4
|
var readJson = (filePath) => JSON.parse(readFileSync(filePath, "utf-8"));
|
|
5
5
|
var createJsonAdapters = (config) => {
|
|
6
|
+
const pathFor = (spaceId, environment, revision) => {
|
|
7
|
+
if (typeof config.offlineData === "function") return config.offlineData(spaceId, environment, revision);
|
|
8
|
+
return typeof config.offlineData === "string" ? config.offlineData : void 0;
|
|
9
|
+
};
|
|
6
10
|
const getOfflineData = (spaceId, environment, revision) => {
|
|
7
11
|
try {
|
|
8
|
-
const filePath =
|
|
12
|
+
const filePath = pathFor(spaceId, environment, revision);
|
|
13
|
+
if (!filePath) return Promise.resolve(config.offlineData);
|
|
9
14
|
return Promise.resolve(readJson(filePath));
|
|
10
15
|
} catch (err) {
|
|
11
16
|
console.error("[JsonAdapters] Failed to read offlineData:", err.message);
|
|
@@ -13,7 +18,8 @@ var createJsonAdapters = (config) => {
|
|
|
13
18
|
}
|
|
14
19
|
};
|
|
15
20
|
const saveOfflineData = (spaceId, environment, data) => {
|
|
16
|
-
const filePath =
|
|
21
|
+
const filePath = pathFor(spaceId, environment);
|
|
22
|
+
if (!filePath) return Promise.resolve();
|
|
17
23
|
writeFileSync(filePath, JSON.stringify(data, null, 2));
|
|
18
24
|
return Promise.resolve();
|
|
19
25
|
};
|
|
@@ -43,9 +49,8 @@ var createJsonAdapters = (config) => {
|
|
|
43
49
|
};
|
|
44
50
|
return {
|
|
45
51
|
getOfflineData,
|
|
46
|
-
saveOfflineData,
|
|
47
52
|
getSpaceDeployment,
|
|
48
|
-
|
|
53
|
+
...typeof config.offlineData !== "object" ? { saveOfflineData } : {}
|
|
49
54
|
};
|
|
50
55
|
};
|
|
51
56
|
//#endregion
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { CredentialCarrier } from './credentials';
|
|
2
|
+
import { Actor, Identity } from './identity';
|
|
3
|
+
import { Tokens } from './tokens';
|
|
4
|
+
import { SSRSession } from '@plitzi/sdk-shared';
|
|
5
|
+
/**
|
|
6
|
+
* An account, as whatever stores accounts reports one. Deliberately not a user model: these are the only fields any
|
|
7
|
+
* decision here is made on, and a deployment maps its own row onto them.
|
|
8
|
+
*/
|
|
9
|
+
export interface AccountRecord {
|
|
10
|
+
id: number;
|
|
11
|
+
username: string;
|
|
12
|
+
email: string;
|
|
13
|
+
/** Suspended, deactivated, whatever the deployment calls it — an inactive account never gets a session. */
|
|
14
|
+
active: boolean;
|
|
15
|
+
/** Confirmed their address. An unverified account may still sign in; what it may *do* is a matter for RBAC. */
|
|
16
|
+
verified: boolean;
|
|
17
|
+
/** Absent for accounts that have no password — one created through an identity provider, for instance. */
|
|
18
|
+
passwordHash?: string;
|
|
19
|
+
/** Unix seconds, for the refresh credential this account currently holds. */
|
|
20
|
+
refreshExpiresAt?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface AccountAccess {
|
|
23
|
+
roles: string[];
|
|
24
|
+
permissions: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The account store, as auth needs to see it. Every method is optional except the three the session cycle cannot do
|
|
28
|
+
* without, and **what is absent decides what this server offers**: a deployment with no `createAccount` has no
|
|
29
|
+
* signup, and its route answers 404 rather than failing at runtime. That rule is what lets one server serve a
|
|
30
|
+
* deployment with its own user table and one that signs everybody in through an external provider.
|
|
31
|
+
*/
|
|
32
|
+
export interface AccountAdapters {
|
|
33
|
+
/** Persist a freshly minted pair. Storing it is what retires the previous one — the whole of rotation. */
|
|
34
|
+
saveSession: (userId: number, session: SSRSession) => Promise<void>;
|
|
35
|
+
/** Clear the pair, by whichever half the caller holds, or by account. */
|
|
36
|
+
clearSession: (target: {
|
|
37
|
+
accessToken?: string;
|
|
38
|
+
refreshToken?: string;
|
|
39
|
+
userId?: number;
|
|
40
|
+
}) => Promise<void>;
|
|
41
|
+
/** Global roles and permissions, for the body a grant answers with. */
|
|
42
|
+
loadAccess: (userId: number) => Promise<AccountAccess>;
|
|
43
|
+
findByUsername?: (username: string) => Promise<AccountRecord | undefined>;
|
|
44
|
+
findByRefreshToken?: (token: string) => Promise<AccountRecord | undefined>;
|
|
45
|
+
createAccount?: (account: {
|
|
46
|
+
username: string;
|
|
47
|
+
email: string;
|
|
48
|
+
passwordHash: string;
|
|
49
|
+
}) => Promise<AccountRecord>;
|
|
50
|
+
findByEmail?: (email: string) => Promise<AccountRecord | undefined>;
|
|
51
|
+
setPassword?: (userId: number, passwordHash: string) => Promise<void>;
|
|
52
|
+
setResetToken?: (userId: number, token: string) => Promise<void>;
|
|
53
|
+
findByResetToken?: (token: string) => Promise<AccountRecord | undefined>;
|
|
54
|
+
setValidationToken?: (userId: number, token: string) => Promise<void>;
|
|
55
|
+
findByValidationToken?: (token: string) => Promise<AccountRecord | undefined>;
|
|
56
|
+
markVerified?: (userId: number) => Promise<void>;
|
|
57
|
+
/** Called for validation and password-reset mail. Without it neither flow is offered. */
|
|
58
|
+
sendMail?: (message: {
|
|
59
|
+
to: string;
|
|
60
|
+
template: string;
|
|
61
|
+
data: Record<string, string>;
|
|
62
|
+
}) => Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Turn a credential the browser obtained from an identity provider into an account here. Everything that decides
|
|
65
|
+
* whether the credential is any good — which providers this deployment trusts, and that the token was minted for
|
|
66
|
+
* *this* application — lives in the implementation, because only it knows.
|
|
67
|
+
*/
|
|
68
|
+
exchangeCredential?: (provider: string, token: string, carrier: CredentialCarrier) => Promise<AccountRecord | {
|
|
69
|
+
error: string;
|
|
70
|
+
status?: number;
|
|
71
|
+
} | undefined>;
|
|
72
|
+
}
|
|
73
|
+
export interface AuthApiConfig {
|
|
74
|
+
/** Compare a password against a stored hash. A deployment picks its own algorithm; nothing here assumes one. */
|
|
75
|
+
verifyPassword?: (plain: string, hash: string) => Promise<boolean>;
|
|
76
|
+
hashPassword?: (plain: string) => Promise<string>;
|
|
77
|
+
/** Opaque, single-use strings for validation and reset links. */
|
|
78
|
+
generateToken?: () => string;
|
|
79
|
+
/** Whether a new account may sign in immediately or has to confirm its address first. */
|
|
80
|
+
verifyOnSignup?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/** What a handler answers: a body, and optionally what should happen to the session cookies. */
|
|
83
|
+
export type AuthOutcome = {
|
|
84
|
+
ok: true;
|
|
85
|
+
status?: number;
|
|
86
|
+
body: object;
|
|
87
|
+
session?: SSRSession;
|
|
88
|
+
endSession?: boolean;
|
|
89
|
+
} | {
|
|
90
|
+
ok: false;
|
|
91
|
+
status: number;
|
|
92
|
+
body: object;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* The HTTP surface of authentication, as functions rather than routes.
|
|
96
|
+
*
|
|
97
|
+
* Nothing here knows about Express, or about this server's own pipeline: a handler is given what the request
|
|
98
|
+
* carried and answers what should be sent, including whether the session cookies should be written or cleared. The
|
|
99
|
+
* binding does the rest, which is what lets the same login live behind an API endpoint and behind a rendered page's
|
|
100
|
+
* form without either owning it.
|
|
101
|
+
*/
|
|
102
|
+
export declare const createAuthApi: ({ tokens, identity, adapters, config }: {
|
|
103
|
+
tokens: Tokens;
|
|
104
|
+
identity: Identity;
|
|
105
|
+
adapters: AccountAdapters;
|
|
106
|
+
config?: AuthApiConfig;
|
|
107
|
+
}) => {
|
|
108
|
+
capabilities: {
|
|
109
|
+
passwordLogin: boolean;
|
|
110
|
+
refresh: boolean;
|
|
111
|
+
signup: boolean;
|
|
112
|
+
passwordReset: boolean;
|
|
113
|
+
emailVerification: boolean;
|
|
114
|
+
exchange: boolean;
|
|
115
|
+
};
|
|
116
|
+
/** What a client reads to know which of the flows below actually exist here. */
|
|
117
|
+
describe: () => AuthOutcome;
|
|
118
|
+
/**
|
|
119
|
+
* Who the caller is, and until when. Reaching a resolved actor at all is the answer to "is the session alive" —
|
|
120
|
+
* the guard refuses with a `reason` when it could not, so a client learns whether to renew or to drop to
|
|
121
|
+
* signed-out from the refusal itself. It costs no query: the actor was resolved before routing.
|
|
122
|
+
*/
|
|
123
|
+
session: (actor?: Actor) => AuthOutcome;
|
|
124
|
+
login: (credentials: Record<string, unknown>) => Promise<AuthOutcome>;
|
|
125
|
+
refresh: (refreshToken?: string) => Promise<AuthOutcome>;
|
|
126
|
+
/** Reachable with an expired access token on purpose, or a live refresh token could never be revoked. */
|
|
127
|
+
logout: (credentials: {
|
|
128
|
+
accessToken?: string;
|
|
129
|
+
refreshToken?: string;
|
|
130
|
+
}) => Promise<AuthOutcome>;
|
|
131
|
+
/**
|
|
132
|
+
* Ends this account's session everywhere, for the case where one leaked. Unlike logout it is authenticated and
|
|
133
|
+
* works by account id, so it can be used from a device that still has a good session while the stolen copy is
|
|
134
|
+
* somewhere else entirely.
|
|
135
|
+
*/
|
|
136
|
+
revokeSessions: (userId?: number) => Promise<AuthOutcome>;
|
|
137
|
+
exchange: (provider: string, token: string, carrier: CredentialCarrier) => Promise<AuthOutcome>;
|
|
138
|
+
signup: (fields: Record<string, unknown>) => Promise<AuthOutcome>;
|
|
139
|
+
/** Answers the same either way: whether an address has an account here is not something a stranger may probe. */
|
|
140
|
+
forgotPassword: (email: string) => Promise<AuthOutcome>;
|
|
141
|
+
resetPassword: (token: string, password: string) => Promise<AuthOutcome>;
|
|
142
|
+
validateAccount: (token: string) => Promise<AuthOutcome>;
|
|
143
|
+
resendVerification: (email: string) => Promise<AuthOutcome>;
|
|
144
|
+
/** Exposed so a deployment can mint a session outside the flows above — a rendered page's login form. */
|
|
145
|
+
issueSession: (userId: number) => Promise<SSRSession>;
|
|
146
|
+
resolveActor: (carrier: CredentialCarrier) => Promise<import('./identity').ActorResult>;
|
|
147
|
+
};
|
|
148
|
+
export type AuthApi = ReturnType<typeof createAuthApi>;
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
//#region src/core/auth/api.ts
|
|
2
|
+
var refuse = (status, error, reason) => ({
|
|
3
|
+
ok: false,
|
|
4
|
+
status,
|
|
5
|
+
body: reason ? {
|
|
6
|
+
error,
|
|
7
|
+
reason
|
|
8
|
+
} : { error }
|
|
9
|
+
});
|
|
10
|
+
var NOT_OFFERED = refuse(404, "Not found");
|
|
11
|
+
/**
|
|
12
|
+
* A field from a request body, as a string. Numbers count: JSON carries an all-digits password as a number, and a
|
|
13
|
+
* client that sends one has supplied a password — refusing it as "credentials are required" is a lie about what
|
|
14
|
+
* arrived. Objects and arrays do not, since `[object Object]` is not a value anybody sent.
|
|
15
|
+
*/
|
|
16
|
+
var asText = (value) => {
|
|
17
|
+
if (typeof value === "string") return value;
|
|
18
|
+
return typeof value === "number" && Number.isFinite(value) ? String(value) : "";
|
|
19
|
+
};
|
|
20
|
+
var asString = (value) => asText(value).trim();
|
|
21
|
+
/**
|
|
22
|
+
* The HTTP surface of authentication, as functions rather than routes.
|
|
23
|
+
*
|
|
24
|
+
* Nothing here knows about Express, or about this server's own pipeline: a handler is given what the request
|
|
25
|
+
* carried and answers what should be sent, including whether the session cookies should be written or cleared. The
|
|
26
|
+
* binding does the rest, which is what lets the same login live behind an API endpoint and behind a rendered page's
|
|
27
|
+
* form without either owning it.
|
|
28
|
+
*/
|
|
29
|
+
var createAuthApi = ({ tokens, identity, adapters, config = {} }) => {
|
|
30
|
+
const { verifyPassword, hashPassword, generateToken, verifyOnSignup = false } = config;
|
|
31
|
+
/**
|
|
32
|
+
* What this deployment offers, decided by what it supplied and nothing else.
|
|
33
|
+
*
|
|
34
|
+
* There used to be a parallel set of `features` switches. They were redundant in every case — each flow reads
|
|
35
|
+
* adapters that no other flow reads, so leaving one out is already how you decline it — and two ways of saying
|
|
36
|
+
* the same thing invite the state where they disagree: an adapter wired up, the flag forgotten, and an endpoint
|
|
37
|
+
* that answers 404 for no reason anyone can see. Declining a flow is now one act: do not implement it.
|
|
38
|
+
*/
|
|
39
|
+
const capabilities = {
|
|
40
|
+
passwordLogin: !!adapters.findByUsername && !!verifyPassword,
|
|
41
|
+
refresh: !!adapters.findByRefreshToken,
|
|
42
|
+
signup: !!adapters.createAccount && !!hashPassword,
|
|
43
|
+
passwordReset: !!adapters.findByEmail && !!adapters.setResetToken && !!hashPassword,
|
|
44
|
+
emailVerification: !!adapters.findByValidationToken && !!adapters.markVerified,
|
|
45
|
+
exchange: !!adapters.exchangeCredential
|
|
46
|
+
};
|
|
47
|
+
const issue = async (userId) => {
|
|
48
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
49
|
+
const session = {
|
|
50
|
+
token: tokens.generateUserToken(userId),
|
|
51
|
+
expiresAt: now + tokens.lifetimes.access,
|
|
52
|
+
refreshToken: tokens.generateRefreshToken(userId),
|
|
53
|
+
refreshExpiresAt: now + tokens.lifetimes.refresh
|
|
54
|
+
};
|
|
55
|
+
await adapters.saveSession(userId, session);
|
|
56
|
+
return session;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The body a grant answers with. `details` is the same object the session endpoint returns, deliberately: it makes
|
|
60
|
+
* a grant an identity, so a client that has just signed in or renewed knows who it is without a second request.
|
|
61
|
+
*/
|
|
62
|
+
const grantBody = async (account, session) => {
|
|
63
|
+
const access = await adapters.loadAccess(account.id);
|
|
64
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
details: {
|
|
68
|
+
id: account.id,
|
|
69
|
+
username: account.username,
|
|
70
|
+
email: account.email,
|
|
71
|
+
verified: account.verified,
|
|
72
|
+
roles: access.roles,
|
|
73
|
+
permissions: access.permissions
|
|
74
|
+
},
|
|
75
|
+
access_token: session.token,
|
|
76
|
+
expire_in: Math.max(0, session.expiresAt - now),
|
|
77
|
+
expire_at: session.expiresAt,
|
|
78
|
+
refresh_token: session.refreshToken,
|
|
79
|
+
refresh_expire_in: Math.max(0, (session.refreshExpiresAt ?? 0) - now),
|
|
80
|
+
refresh_expire_at: session.refreshExpiresAt
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
capabilities,
|
|
85
|
+
/** What a client reads to know which of the flows below actually exist here. */
|
|
86
|
+
describe: () => ({
|
|
87
|
+
ok: true,
|
|
88
|
+
body: { features: capabilities }
|
|
89
|
+
}),
|
|
90
|
+
/**
|
|
91
|
+
* Who the caller is, and until when. Reaching a resolved actor at all is the answer to "is the session alive" —
|
|
92
|
+
* the guard refuses with a `reason` when it could not, so a client learns whether to renew or to drop to
|
|
93
|
+
* signed-out from the refusal itself. It costs no query: the actor was resolved before routing.
|
|
94
|
+
*/
|
|
95
|
+
session: (actor) => {
|
|
96
|
+
if (!actor) return refuse(401, "Not authenticated", "missing");
|
|
97
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
98
|
+
return {
|
|
99
|
+
ok: true,
|
|
100
|
+
body: {
|
|
101
|
+
success: true,
|
|
102
|
+
details: {
|
|
103
|
+
id: actor.id,
|
|
104
|
+
username: actor.username,
|
|
105
|
+
email: actor.email,
|
|
106
|
+
verified: actor.verified,
|
|
107
|
+
roles: actor.roles,
|
|
108
|
+
permissions: actor.permissions
|
|
109
|
+
},
|
|
110
|
+
access_token: actor.token,
|
|
111
|
+
expire_in: Math.max(0, actor.expiresAt - now),
|
|
112
|
+
expire_at: actor.expiresAt
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
login: async (credentials) => {
|
|
117
|
+
if (!capabilities.passwordLogin) return NOT_OFFERED;
|
|
118
|
+
const username = asString(credentials.username);
|
|
119
|
+
const password = asText(credentials.password);
|
|
120
|
+
if (!username || !password) return refuse(400, "A username and a password are required");
|
|
121
|
+
const account = await adapters.findByUsername?.(username);
|
|
122
|
+
if (!account) return refuse(401, "Invalid credentials");
|
|
123
|
+
if (!account.active) return refuse(401, "Account is not active");
|
|
124
|
+
if (!account.passwordHash || !await verifyPassword?.(password, account.passwordHash)) return refuse(401, "Invalid credentials");
|
|
125
|
+
const session = await issue(account.id);
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
body: await grantBody(account, session),
|
|
129
|
+
session
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
refresh: async (refreshToken) => {
|
|
133
|
+
if (!capabilities.refresh) return NOT_OFFERED;
|
|
134
|
+
if (!refreshToken) return refuse(400, "Refresh token is required");
|
|
135
|
+
const account = await adapters.findByRefreshToken?.(refreshToken);
|
|
136
|
+
if (!account || !account.refreshExpiresAt || account.refreshExpiresAt < Math.floor(Date.now() / 1e3)) return refuse(401, "Invalid or expired refresh token", "expired");
|
|
137
|
+
if (!account.active) return refuse(401, "Account is not active", "inactive");
|
|
138
|
+
const session = await issue(account.id);
|
|
139
|
+
return {
|
|
140
|
+
ok: true,
|
|
141
|
+
body: await grantBody(account, session),
|
|
142
|
+
session
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
/** Reachable with an expired access token on purpose, or a live refresh token could never be revoked. */
|
|
146
|
+
logout: async (credentials) => {
|
|
147
|
+
if (credentials.accessToken || credentials.refreshToken) await adapters.clearSession(credentials);
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
body: { message: "Logged out successfully" },
|
|
151
|
+
endSession: true
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Ends this account's session everywhere, for the case where one leaked. Unlike logout it is authenticated and
|
|
156
|
+
* works by account id, so it can be used from a device that still has a good session while the stolen copy is
|
|
157
|
+
* somewhere else entirely.
|
|
158
|
+
*/
|
|
159
|
+
revokeSessions: async (userId) => {
|
|
160
|
+
if (!userId) return refuse(401, "Not authenticated", "missing");
|
|
161
|
+
await adapters.clearSession({ userId });
|
|
162
|
+
return {
|
|
163
|
+
ok: true,
|
|
164
|
+
body: { message: "All sessions revoked" },
|
|
165
|
+
endSession: true
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
exchange: async (provider, token, carrier) => {
|
|
169
|
+
if (!capabilities.exchange) return NOT_OFFERED;
|
|
170
|
+
if (!provider || !token) return refuse(400, "A provider and a token are required");
|
|
171
|
+
const result = await adapters.exchangeCredential?.(provider, token, carrier);
|
|
172
|
+
if (!result) return refuse(401, "Token Invalid", "revoked");
|
|
173
|
+
if ("error" in result) return refuse(result.status ?? 400, result.error, "revoked");
|
|
174
|
+
const session = await issue(result.id);
|
|
175
|
+
return {
|
|
176
|
+
ok: true,
|
|
177
|
+
body: await grantBody(result, session),
|
|
178
|
+
session
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
signup: async (fields) => {
|
|
182
|
+
if (!capabilities.signup) return NOT_OFFERED;
|
|
183
|
+
const username = asString(fields.username);
|
|
184
|
+
const email = asString(fields.email);
|
|
185
|
+
const password = asText(fields.password);
|
|
186
|
+
if (!username || !email || !password) return refuse(400, "A username, an email and a password are required");
|
|
187
|
+
if (await adapters.findByUsername?.(username) ?? await adapters.findByEmail?.(email)) return refuse(400, "User already exists");
|
|
188
|
+
if (!adapters.createAccount || !hashPassword) return NOT_OFFERED;
|
|
189
|
+
const account = await adapters.createAccount({
|
|
190
|
+
username,
|
|
191
|
+
email,
|
|
192
|
+
passwordHash: await hashPassword(password)
|
|
193
|
+
});
|
|
194
|
+
if (!verifyOnSignup && capabilities.emailVerification && generateToken && adapters.setValidationToken) {
|
|
195
|
+
const validationToken = generateToken();
|
|
196
|
+
await adapters.setValidationToken(account.id, validationToken);
|
|
197
|
+
await adapters.sendMail?.({
|
|
198
|
+
to: email,
|
|
199
|
+
template: "validation",
|
|
200
|
+
data: {
|
|
201
|
+
username,
|
|
202
|
+
validationToken
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
ok: true,
|
|
208
|
+
status: 201,
|
|
209
|
+
body: {
|
|
210
|
+
message: "User created successfully",
|
|
211
|
+
userId: account.id
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
/** Answers the same either way: whether an address has an account here is not something a stranger may probe. */
|
|
216
|
+
forgotPassword: async (email) => {
|
|
217
|
+
if (!capabilities.passwordReset || !generateToken) return NOT_OFFERED;
|
|
218
|
+
const account = await adapters.findByEmail?.(asString(email));
|
|
219
|
+
if (account) {
|
|
220
|
+
const resetToken = generateToken();
|
|
221
|
+
await adapters.setResetToken?.(account.id, resetToken);
|
|
222
|
+
await adapters.sendMail?.({
|
|
223
|
+
to: account.email,
|
|
224
|
+
template: "password-reset",
|
|
225
|
+
data: {
|
|
226
|
+
username: account.username,
|
|
227
|
+
resetToken
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
ok: true,
|
|
233
|
+
body: { message: "Password reset email sent" }
|
|
234
|
+
};
|
|
235
|
+
},
|
|
236
|
+
resetPassword: async (token, password) => {
|
|
237
|
+
if (!capabilities.passwordReset || !hashPassword) return NOT_OFFERED;
|
|
238
|
+
if (!token || !password) return refuse(400, "A token and a password are required");
|
|
239
|
+
const account = await adapters.findByResetToken?.(token);
|
|
240
|
+
if (!account) return refuse(400, "Invalid or expired token");
|
|
241
|
+
await adapters.setPassword?.(account.id, await hashPassword(password));
|
|
242
|
+
await adapters.setResetToken?.(account.id, "");
|
|
243
|
+
await adapters.clearSession({ userId: account.id });
|
|
244
|
+
return {
|
|
245
|
+
ok: true,
|
|
246
|
+
body: { message: "Password reset successfully" },
|
|
247
|
+
endSession: true
|
|
248
|
+
};
|
|
249
|
+
},
|
|
250
|
+
validateAccount: async (token) => {
|
|
251
|
+
if (!capabilities.emailVerification) return NOT_OFFERED;
|
|
252
|
+
const account = await adapters.findByValidationToken?.(token);
|
|
253
|
+
if (!account) return refuse(400, "Invalid or expired token");
|
|
254
|
+
await adapters.markVerified?.(account.id);
|
|
255
|
+
return {
|
|
256
|
+
ok: true,
|
|
257
|
+
body: { message: "Account validated successfully" }
|
|
258
|
+
};
|
|
259
|
+
},
|
|
260
|
+
resendVerification: async (email) => {
|
|
261
|
+
if (!capabilities.emailVerification || !generateToken) return NOT_OFFERED;
|
|
262
|
+
const account = await adapters.findByEmail?.(asString(email));
|
|
263
|
+
if (account && !account.verified) {
|
|
264
|
+
const validationToken = generateToken();
|
|
265
|
+
await adapters.setValidationToken?.(account.id, validationToken);
|
|
266
|
+
await adapters.sendMail?.({
|
|
267
|
+
to: account.email,
|
|
268
|
+
template: "validation",
|
|
269
|
+
data: {
|
|
270
|
+
username: account.username,
|
|
271
|
+
validationToken
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
ok: true,
|
|
277
|
+
body: { message: "Verification email resent" }
|
|
278
|
+
};
|
|
279
|
+
},
|
|
280
|
+
/** Exposed so a deployment can mint a session outside the flows above — a rendered page's login form. */
|
|
281
|
+
issueSession: issue,
|
|
282
|
+
resolveActor: identity.resolveActor
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
//#endregion
|
|
286
|
+
export { createAuthApi };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { CredentialCarrier } from './credentials';
|
|
2
|
+
import { Actor, Grant, Identity } from './identity';
|
|
3
|
+
import { AuthFailure } from './tokens';
|
|
4
|
+
/**
|
|
5
|
+
* Strings match exactly — a prefix test would make '/' match every route and silently expose everything under it.
|
|
6
|
+
* Regexes and predicates cover the cases that genuinely need to look at sub-paths (a predicate so social-auth routes
|
|
7
|
+
* can resolve a provider registry rather than trusting the shape of a URL).
|
|
8
|
+
*/
|
|
9
|
+
export type PathMatcher = string | RegExp | ((path: string) => boolean);
|
|
10
|
+
/**
|
|
11
|
+
* Both credentials are resolved for every non-public request; the requirement only says which must be there.
|
|
12
|
+
* Resolving the one that is absent is nearly free — a token of the wrong kind fails on its `scope` claim before any
|
|
13
|
+
* database lookup.
|
|
14
|
+
*/
|
|
15
|
+
export type Requirement =
|
|
16
|
+
/** No credential is read and nothing is checked. */
|
|
17
|
+
'public'
|
|
18
|
+
/**
|
|
19
|
+
* Neither is required. Authorization happens deeper in (GraphQL guards each operation), so the transport must let
|
|
20
|
+
* anonymous requests through to be refused there properly rather than with a bare 401.
|
|
21
|
+
*/
|
|
22
|
+
| 'optional'
|
|
23
|
+
/** A valid space grant. Says which space — never that the caller may change it. */
|
|
24
|
+
| 'grant'
|
|
25
|
+
/** A verified account. */
|
|
26
|
+
| 'actor'
|
|
27
|
+
/**
|
|
28
|
+
* Both: the space is named by the token, the authority comes from the session. What anything that writes on
|
|
29
|
+
* behalf of a person needs.
|
|
30
|
+
*/
|
|
31
|
+
| 'grant+actor';
|
|
32
|
+
export interface AuthPolicy {
|
|
33
|
+
rules: {
|
|
34
|
+
match: PathMatcher[];
|
|
35
|
+
requirement: Requirement;
|
|
36
|
+
}[];
|
|
37
|
+
fallback: Requirement;
|
|
38
|
+
}
|
|
39
|
+
export type AuthorizeResult = {
|
|
40
|
+
ok: true;
|
|
41
|
+
actor?: Actor;
|
|
42
|
+
grant?: Grant;
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
status: number;
|
|
46
|
+
reason: AuthFailure;
|
|
47
|
+
};
|
|
48
|
+
export declare const requirementFor: (policy: AuthPolicy, path: string) => Requirement;
|
|
49
|
+
/**
|
|
50
|
+
* Decides whether a request may proceed, and with what identity — the same decision on every transport, which is
|
|
51
|
+
* the point of it living here rather than inside one framework's middleware. Callers bind it to their own: Express
|
|
52
|
+
* puts the result on `req` and answers 401 itself, this server's pipeline does the same with its own response.
|
|
53
|
+
*/
|
|
54
|
+
export declare const createAuthorizer: (identity: Identity, policy: AuthPolicy) => (carrier: CredentialCarrier, path: string) => Promise<AuthorizeResult>;
|
|
55
|
+
export type Authorizer = ReturnType<typeof createAuthorizer>;
|
|
56
|
+
export type PermissionCheck = {
|
|
57
|
+
ok: true;
|
|
58
|
+
} | {
|
|
59
|
+
ok: false;
|
|
60
|
+
status: number;
|
|
61
|
+
error: string;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* A global capability, checked off the actor the guard already resolved — no query. This is the whole of RBAC that
|
|
65
|
+
* applies outside a space: platform-wide routes rather than "may you touch this space", which is `identity.can()` and
|
|
66
|
+
* needs the membership half too.
|
|
67
|
+
*
|
|
68
|
+
* An answer rather than a middleware, so it reads the same from any host. The distinction it exists to make is 401
|
|
69
|
+
* against 403: "nobody is here" and "you are here and this is not yours" are different facts, and collapsing them
|
|
70
|
+
* tells a signed-in caller to sign in again.
|
|
71
|
+
*/
|
|
72
|
+
export declare const checkPermission: (actor: Actor | undefined, permission: string) => PermissionCheck;
|
|
73
|
+
/** What a membership row has to say for the check below. A deployment's own row will carry far more. */
|
|
74
|
+
export interface MembershipFacts {
|
|
75
|
+
isOwner: boolean;
|
|
76
|
+
}
|
|
77
|
+
export type SpaceAccessCheck = {
|
|
78
|
+
ok: true;
|
|
79
|
+
} | {
|
|
80
|
+
ok: false;
|
|
81
|
+
status: number;
|
|
82
|
+
error: string;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The space half: may this actor act on this space at all, and is being its owner required?
|
|
86
|
+
*
|
|
87
|
+
* The answer that matters is the middle one. A non-member gets **404, not 403** — telling a stranger "you may not
|
|
88
|
+
* touch this space" confirms the space exists, and whether a given slug belongs to somebody is not a fact an
|
|
89
|
+
* outsider gets to establish by asking. Owners and members are told apart afterwards, because by then the caller has
|
|
90
|
+
* already proved they belong there and 403 gives away nothing.
|
|
91
|
+
*
|
|
92
|
+
* Resolving the membership is the deployment's — its tables, and whether a route names a space by id or by slug.
|
|
93
|
+
*/
|
|
94
|
+
export declare const checkSpaceAccess: (actor: Actor | undefined, membership: MembershipFacts | undefined, { owner }?: {
|
|
95
|
+
owner?: boolean;
|
|
96
|
+
}) => SpaceAccessCheck;
|