bazis 0.96.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/LICENSE +21 -0
- package/README.md +146 -0
- package/cli/build.ts +147 -0
- package/cli/codegen.ts +40 -0
- package/cli/generateModule.ts +187 -0
- package/cli/generateProject.ts +183 -0
- package/cli/main.ts +125 -0
- package/cli/moduleRegistration.ts +127 -0
- package/cli/naming.ts +124 -0
- package/cli/parseCli.ts +151 -0
- package/cli/templates/module.ts +497 -0
- package/cli/templates/pack.ts +76 -0
- package/cli/templates/passport.ts +178 -0
- package/core/agent/AgentContextBuilder.ts +567 -0
- package/core/agent/AgentDataDefinition.ts +8 -0
- package/core/agent/AgentRegistry.ts +539 -0
- package/core/agent/AgentRuntime.ts +47 -0
- package/core/agent/AgentToolExecutor.ts +2130 -0
- package/core/agent/AgentToolHooks.ts +39 -0
- package/core/agent/ModelProvider.ts +21 -0
- package/core/agent/README.md +229 -0
- package/core/agent/Tool.contract.ts +20 -0
- package/core/agent/decorators/Agent.ts +11 -0
- package/core/agent/decorators/Prompt.ts +11 -0
- package/core/agent/decorators/Task.ts +29 -0
- package/core/agent/decorators/Tool.ts +12 -0
- package/core/agent/errors.ts +43 -0
- package/core/agent/generated/catalog.ts +26 -0
- package/core/agent/index.ts +170 -0
- package/core/agent/internal/AgentExecutionDriver.ts +1497 -0
- package/core/agent/internal/AgentExecutionState.ts +775 -0
- package/core/agent/internal/AgentJsonSchema.ts +150 -0
- package/core/agent/internal/AgentModelBinding.ts +57 -0
- package/core/agent/internal/Schema.contract.ts +36 -0
- package/core/agent/internal/ToolAudit.projector.ts +163 -0
- package/core/agent/internal/ToolContract.validator.ts +102 -0
- package/core/agent/metadata.ts +398 -0
- package/core/agent/moduleContributions-v1.ts +113 -0
- package/core/agent/semantic.ts +903 -0
- package/core/agent/session/codec.ts +33 -0
- package/core/agent/session/contracts.ts +96 -0
- package/core/agent/session/entities.ts +84 -0
- package/core/agent/session/protector.ts +92 -0
- package/core/app/index.ts +5 -0
- package/core/app/runApp.ts +293 -0
- package/core/app/ui/index.ts +29 -0
- package/core/app/ui/uiProfileResolver.ts +966 -0
- package/core/app/ui/uiSurfaceHosting.ts +38 -0
- package/core/app/ui/uiSurfaceHttp.ts +476 -0
- package/core/background/BackgroundService.ts +223 -0
- package/core/background/backgroundModule.ts +42 -0
- package/core/background/decorator.ts +43 -0
- package/core/background/delay.ts +27 -0
- package/core/background/index.ts +15 -0
- package/core/cache/COMPATIBILITY.md +13 -0
- package/core/cache/ICache.ts +71 -0
- package/core/cache/MemoryCache.ts +394 -0
- package/core/cache/README.md +83 -0
- package/core/cache/SPEC.md +1355 -0
- package/core/cache/cacheModule.ts +21 -0
- package/core/cache/decorators/Cacheable.ts +38 -0
- package/core/cache/decorators/CacheableRedis.ts +39 -0
- package/core/cache/decorators/OutputCache.ts +33 -0
- package/core/cache/decorators/OutputRedisCache.ts +33 -0
- package/core/cache/decorators/cacheableMetadata.ts +78 -0
- package/core/cache/decorators/cacheableRedisMetadata.ts +81 -0
- package/core/cache/decorators/outputCacheMetadata.ts +71 -0
- package/core/cache/decorators/outputRedisCacheMetadata.ts +77 -0
- package/core/cache/di/classProviderHook.ts +26 -0
- package/core/cache/distributed/CacheCodec.ts +5 -0
- package/core/cache/distributed/DistributedCache.ts +403 -0
- package/core/cache/distributed/DistributedCacheDriver.ts +83 -0
- package/core/cache/distributed/DistributedCacheStores.ts +28 -0
- package/core/cache/distributed/IDistributedCache.ts +40 -0
- package/core/cache/distributed/NamedCacheRegistry.ts +23 -0
- package/core/cache/distributed/codecs.ts +32 -0
- package/core/cache/distributed/index.ts +19 -0
- package/core/cache/errors/CacheError.ts +16 -0
- package/core/cache/http/CachedHttpPayload.ts +213 -0
- package/core/cache/http/applyClientCacheHeaders.ts +61 -0
- package/core/cache/http/buildOutputCacheKey.ts +154 -0
- package/core/cache/http/buildRedisOutputCacheKey.ts +16 -0
- package/core/cache/http/composeOutputCache.ts +130 -0
- package/core/cache/http/outputCacheMiddleware.ts +111 -0
- package/core/cache/http/outputCacheSecurityWarning.ts +58 -0
- package/core/cache/http/outputRedisCacheMiddleware.ts +118 -0
- package/core/cache/index.ts +97 -0
- package/core/cache/internal/AutomaticCacheKey.ts +106 -0
- package/core/cache/internal/CacheKeyGuard.ts +56 -0
- package/core/cache/internal/buildCacheProviders.ts +146 -0
- package/core/cache/internal/normalizeCacheKey.ts +9 -0
- package/core/cache/internal/resolveCachePolicy.ts +32 -0
- package/core/cache/internal/resolveCacheableRedisPolicy.ts +17 -0
- package/core/cache/internal/resolveOutputRedisCachePolicy.ts +17 -0
- package/core/cache/providers/cachedProviders.ts +68 -0
- package/core/cache/services/cacheProxy.ts +243 -0
- package/core/cache/tokens/CACHE_POLICIES.ts +5 -0
- package/core/cache/tokens/DISTRIBUTED_CACHE.ts +30 -0
- package/core/cache/types/CacheEntry.ts +7 -0
- package/core/cache/types/CacheOptions.ts +60 -0
- package/core/cache/types/CachePolicy.ts +74 -0
- package/core/cache/types/CacheableRedisOptions.ts +23 -0
- package/core/cache/types/OutputRedisCacheOptions.ts +25 -0
- package/core/di/README.md +104 -0
- package/core/di/ServiceCollection.ts +185 -0
- package/core/di/ServiceProvider.ts +689 -0
- package/core/di/ServiceScope.ts +61 -0
- package/core/di/container.ts +38 -0
- package/core/di/errors/AmbiguousNamedDependencyError.ts +10 -0
- package/core/di/errors/AsyncResolutionRequiredError.ts +12 -0
- package/core/di/errors/CircularDependencyError.ts +10 -0
- package/core/di/errors/ClassDependenciesMismatchError.ts +15 -0
- package/core/di/errors/DiError.ts +6 -0
- package/core/di/errors/InvalidProviderError.ts +9 -0
- package/core/di/errors/ModuleEncapsulationError.ts +7 -0
- package/core/di/errors/ModuleOwnedProviderConflictError.ts +8 -0
- package/core/di/errors/NamedDependencyNotFoundError.ts +7 -0
- package/core/di/errors/OptionsValidationError.ts +7 -0
- package/core/di/errors/ProviderNotFoundError.ts +10 -0
- package/core/di/errors/ScopeDisposedError.ts +7 -0
- package/core/di/errors/ScopedServiceFromRootError.ts +9 -0
- package/core/di/errors/ServiceValidationError.ts +7 -0
- package/core/di/errors/index.ts +14 -0
- package/core/di/extensions/activator.ts +39 -0
- package/core/di/extensions/application.ts +117 -0
- package/core/di/extensions/hosted-service.ts +124 -0
- package/core/di/extensions/index.ts +23 -0
- package/core/di/extensions/options-reloadable.ts +137 -0
- package/core/di/extensions/options.ts +91 -0
- package/core/di/extensions/service-provider-token.ts +21 -0
- package/core/di/index.ts +97 -0
- package/core/di/internal/GraphValidator.ts +119 -0
- package/core/di/internal/HostedServicePlan.ts +158 -0
- package/core/di/internal/NamedTokenIndex.ts +55 -0
- package/core/di/internal/OpenGenericRegistration.ts +14 -0
- package/core/di/internal/ResolutionPlan.ts +18 -0
- package/core/di/internal/ResolutionScopeState.ts +19 -0
- package/core/di/internal/ResolutionTracker.ts +153 -0
- package/core/di/internal/ScopeLifecycle.ts +159 -0
- package/core/di/internal/ServiceRegistration.ts +14 -0
- package/core/di/internal/ServiceRegistry.ts +252 -0
- package/core/di/internal/classDeps.ts +38 -0
- package/core/di/internal/disposal.ts +58 -0
- package/core/di/internal/providerDeps.ts +26 -0
- package/core/di/module/DI.ts +146 -0
- package/core/di/module/Global.ts +25 -0
- package/core/di/module/Module.ts +44 -0
- package/core/di/module/ModuleRegistrar.ts +69 -0
- package/core/di/module/autoDeps.ts +39 -0
- package/core/di/module/classProviderHooks.ts +66 -0
- package/core/di/module/collectModuleConfigs.ts +57 -0
- package/core/di/module/collectModuleControllers.ts +53 -0
- package/core/di/module/collectModuleUiProfiles.ts +53 -0
- package/core/di/module/createContainer.ts +261 -0
- package/core/di/module/encapsulation.ts +416 -0
- package/core/di/module/encapsulationHooks.ts +36 -0
- package/core/di/module/generatedProviderAttachments.ts +102 -0
- package/core/di/module/index.ts +41 -0
- package/core/di/module/moduleExtensions.ts +35 -0
- package/core/di/module/moduleNameBinding.ts +136 -0
- package/core/di/module/moduleOwnedProviderContributors.ts +409 -0
- package/core/di/module/providerSelection.ts +90 -0
- package/core/di/module/shortcuts.ts +111 -0
- package/core/di/module/types/BazisModule.ts +71 -0
- package/core/di/module/types/DiRegistrar.ts +24 -0
- package/core/di/module/types/index.ts +2 -0
- package/core/di/provider/index.ts +26 -0
- package/core/di/provider/providerGuards.ts +17 -0
- package/core/di/provider/types/AsyncFactoryProvider.ts +15 -0
- package/core/di/provider/types/ClassProvider.ts +18 -0
- package/core/di/provider/types/FactoryProvider.ts +20 -0
- package/core/di/provider/types/KeyedDependency.ts +20 -0
- package/core/di/provider/types/LazyDependency.ts +31 -0
- package/core/di/provider/types/NamedDependency.ts +16 -0
- package/core/di/provider/types/Provider.ts +10 -0
- package/core/di/provider/types/ProviderDefinition.ts +11 -0
- package/core/di/provider/types/ProviderDependencyList.ts +11 -0
- package/core/di/provider/types/ProviderLifetime.ts +1 -0
- package/core/di/provider/types/ProviderOwnership.ts +7 -0
- package/core/di/provider/types/ResolvedDeps.ts +18 -0
- package/core/di/provider/types/ValueProvider.ts +6 -0
- package/core/di/provider/types/index.ts +13 -0
- package/core/di/token.ts +84 -0
- package/core/di/types/BuildServiceProviderOptions.ts +4 -0
- package/core/di/types/ServiceKey.ts +1 -0
- package/core/di/types/ServiceResolver.ts +16 -0
- package/core/di/types/index.ts +3 -0
- package/core/generatedFingerprint.ts +60 -0
- package/core/generatedRuntime.ts +187 -0
- package/core/grpc/Grpc.module.ts +23 -0
- package/core/grpc/GrpcBinding.contract.ts +35 -0
- package/core/grpc/GrpcCall.ts +73 -0
- package/core/grpc/GrpcClient.ts +172 -0
- package/core/grpc/GrpcClientCall.ts +267 -0
- package/core/grpc/GrpcError.ts +19 -0
- package/core/grpc/GrpcRequest.binding.ts +45 -0
- package/core/grpc/GrpcServer.ts +204 -0
- package/core/grpc/GrpcStatus.ts +8 -0
- package/core/grpc/GrpcTransport.ts +174 -0
- package/core/grpc/Metadata.ts +73 -0
- package/core/grpc/ProtoCodec.ts +225 -0
- package/core/grpc/ProtoParser.ts +192 -0
- package/core/grpc/ProtoReader.ts +34 -0
- package/core/grpc/ProtoSchema.ts +52 -0
- package/core/grpc/ServerCredentials.ts +30 -0
- package/core/grpc/clientContracts.ts +39 -0
- package/core/grpc/contracts.ts +45 -0
- package/core/grpc/decorators.ts +82 -0
- package/core/grpc/grpcClientProvider.ts +9 -0
- package/core/grpc/index.ts +17 -0
- package/core/grpc/moduleControllers.ts +38 -0
- package/core/grpc/protobuf.ts +80 -0
- package/core/grpc/serviceDefinition.ts +20 -0
- package/core/http/Authorization/Authorize.ts +52 -0
- package/core/http/Authorization/authorizeComposer.ts +31 -0
- package/core/http/Authorization/metadata.ts +158 -0
- package/core/http/Binding/ParameterBinder.ts +109 -0
- package/core/http/Binding/RequestModel.ts +27 -0
- package/core/http/Binding/autoBindings.ts +125 -0
- package/core/http/Binding/bindings.ts +19 -0
- package/core/http/Binding/convert.ts +48 -0
- package/core/http/Binding/generatedSpec.ts +18 -0
- package/core/http/Binding/listModelRegistry.ts +47 -0
- package/core/http/Binding/modelBinder.ts +345 -0
- package/core/http/Binding/modelValidator.ts +30 -0
- package/core/http/Binding/requestModelRegistry.ts +117 -0
- package/core/http/Decorators/attributes.ts +92 -0
- package/core/http/Decorators/controller.ts +24 -0
- package/core/http/Decorators/metadata.ts +107 -0
- package/core/http/Decorators/routes.ts +131 -0
- package/core/http/Errors/HttpError.ts +92 -0
- package/core/http/HttpContext/HttpContext.ts +148 -0
- package/core/http/HttpContext/ResponseBuilder.ts +37 -0
- package/core/http/HttpContext/inspectableRedirects.ts +47 -0
- package/core/http/HttpContext/principal.ts +24 -0
- package/core/http/HttpContext/responseLifetime.ts +45 -0
- package/core/http/HttpServer.ts +627 -0
- package/core/http/Middleware/accessLog.ts +90 -0
- package/core/http/Middleware/cors.ts +160 -0
- package/core/http/Middleware/errorHandler.ts +100 -0
- package/core/http/Middleware/pipeline.ts +21 -0
- package/core/http/Middleware/rateLimit.ts +104 -0
- package/core/http/Middleware/securityHeaders.ts +118 -0
- package/core/http/Middleware/types.ts +19 -0
- package/core/http/OpenApi/generatedOpenApiRegistry.ts +102 -0
- package/core/http/OpenApi/openApiDocs.ts +75 -0
- package/core/http/OpenApi/openApiDocument.ts +356 -0
- package/core/http/README.md +139 -0
- package/core/http/Results/HttpResult.ts +19 -0
- package/core/http/Results/normalize.ts +93 -0
- package/core/http/Results/results.ts +70 -0
- package/core/http/Routing/Router.ts +201 -0
- package/core/http/Routing/RouterBuilder.ts +184 -0
- package/core/http/Routing/template.ts +112 -0
- package/core/http/SPEC.md +981 -0
- package/core/http/Versioning/VersionReader.ts +20 -0
- package/core/http/WebSocketUpgrade.ts +29 -0
- package/core/http/composeRouteMiddlewareComposers.ts +21 -0
- package/core/http/correlation/createCorrelationIdMiddleware.ts +79 -0
- package/core/http/httpModule.ts +48 -0
- package/core/http/index.ts +140 -0
- package/core/http/middlewareTokens.ts +48 -0
- package/core/http/options.ts +134 -0
- package/core/http-client/index.ts +105 -0
- package/core/infra/Infra.ts +158 -0
- package/core/infra/InfraConnector.ts +86 -0
- package/core/infra/InfraLifecycle.ts +86 -0
- package/core/infra/cache/RedisDistributedCacheBackend.ts +88 -0
- package/core/infra/cache/RedisDistributedCacheDriver.ts +186 -0
- package/core/infra/cache/index.ts +7 -0
- package/core/infra/connectorConfig.ts +29 -0
- package/core/infra/connectorIdentity.ts +39 -0
- package/core/infra/connectors/codex/CodexAppServer.ts +146 -0
- package/core/infra/connectors/codex/CodexAppServerClient.ts +258 -0
- package/core/infra/connectors/codex/CodexPolicy.ts +114 -0
- package/core/infra/connectors/codex/CodexTurn.ts +133 -0
- package/core/infra/connectors/codex/contracts.ts +82 -0
- package/core/infra/connectors/codex.ts +26 -0
- package/core/infra/connectors/llm.ts +78 -0
- package/core/infra/connectors/llmRouter.ts +443 -0
- package/core/infra/connectors/openaiCompatible.ts +590 -0
- package/core/infra/connectors/openaiTextStream.ts +134 -0
- package/core/infra/connectors/opensearch.ts +307 -0
- package/core/infra/connectors/postgres.ts +105 -0
- package/core/infra/connectors/redis.ts +132 -0
- package/core/infra/index.ts +58 -0
- package/core/kernel/ApplicationLifetime.ts +91 -0
- package/core/kernel/Bazis.ts +73 -0
- package/core/kernel/Environment.ts +53 -0
- package/core/kernel/Kernel.ts +391 -0
- package/core/kernel/KernelBuilder.ts +172 -0
- package/core/kernel/LifecycleCoordinator.ts +204 -0
- package/core/kernel/README.md +66 -0
- package/core/kernel/SupervisedHostedService.ts +147 -0
- package/core/kernel/config/ConfigRegistry.ts +48 -0
- package/core/kernel/config/Configuration.ts +110 -0
- package/core/kernel/config/README.md +62 -0
- package/core/kernel/config/Secret.ts +29 -0
- package/core/kernel/config/addConfigOptions.ts +63 -0
- package/core/kernel/config/defineConfig.ts +211 -0
- package/core/kernel/config/sources.ts +123 -0
- package/core/kernel/correlation/requestContext.ts +57 -0
- package/core/kernel/errors/ConfigKeyMissingError.ts +7 -0
- package/core/kernel/errors/KernelError.ts +7 -0
- package/core/kernel/errors/ShutdownTimeoutError.ts +7 -0
- package/core/kernel/errors/StartupAbortedError.ts +7 -0
- package/core/kernel/errors/StartupTimeoutError.ts +7 -0
- package/core/kernel/errors/index.ts +5 -0
- package/core/kernel/events/EventBus.ts +140 -0
- package/core/kernel/events/EventToken.ts +17 -0
- package/core/kernel/events/eventSubscribers.ts +126 -0
- package/core/kernel/events/kernelEvents.ts +16 -0
- package/core/kernel/events/onEvent.ts +32 -0
- package/core/kernel/health/HealthCheckContracts.ts +42 -0
- package/core/kernel/health/HealthService.ts +93 -0
- package/core/kernel/index.ts +96 -0
- package/core/kernel/internal/awaitAbortable.ts +18 -0
- package/core/kernel/internal/awaitShutdown.ts +21 -0
- package/core/kernel/internal/reportDiagnosticFailure.ts +8 -0
- package/core/kernel/internal/validateTimeout.ts +8 -0
- package/core/kernel/lifecycleHooks.ts +18 -0
- package/core/kernel/logging/ConsoleLogger.ts +68 -0
- package/core/kernel/logging/Logger.ts +22 -0
- package/core/kernel/types/ConfigSource.ts +9 -0
- package/core/kernel/types/EnvironmentName.ts +1 -0
- package/core/kernel/types/KernelOptions.ts +23 -0
- package/core/kernel/types/LifecycleHook.ts +18 -0
- package/core/kernel/types/index.ts +4 -0
- package/core/orm/DATABASE_PROVIDER.ts +5 -0
- package/core/orm/OrmHostedPlan.validator.ts +55 -0
- package/core/orm/OrmLifecycle.ts +146 -0
- package/core/orm/OrmOwnedStoreLifecycle.ts +96 -0
- package/core/orm/buildOrmProviders.ts +152 -0
- package/core/orm/databaseConnector.ts +108 -0
- package/core/orm/encapsulationHook.ts +19 -0
- package/core/orm/index.ts +95 -0
- package/core/orm/listQuery.ts +198 -0
- package/core/orm/ormModule.ts +173 -0
- package/core/orm/ownedStoreContributions.ts +195 -0
- package/core/orm/registerRepositories.ts +27 -0
- package/core/orm/repository.ts +45 -0
- package/core/orm/strictSchemaHostedIdentity.ts +17 -0
- package/core/scripts/agent-codegen.ts +1166 -0
- package/core/scripts/di-generate-target.ts +90 -0
- package/core/scripts/di-generate.ts +1837 -0
- package/core/scripts/orm-predicate-codegen.ts +33 -0
- package/core/scripts/request-model-codegen.ts +326 -0
- package/core/websocket/DESIGN.md +297 -0
- package/core/websocket/WsRateLimiter.ts +101 -0
- package/core/websocket/adapter/adapter.interface.ts +45 -0
- package/core/websocket/adapter/in-memory.adapter.ts +190 -0
- package/core/websocket/adapter/redis-delivery-scripts.ts +135 -0
- package/core/websocket/adapter/redis-delivery-store.ts +86 -0
- package/core/websocket/adapter/redis-operations.ts +33 -0
- package/core/websocket/adapter/redis.adapter.ts +218 -0
- package/core/websocket/codec/binary.codec.ts +87 -0
- package/core/websocket/codec/json.codec.ts +34 -0
- package/core/websocket/codec/packet-codec.interface.ts +17 -0
- package/core/websocket/decorators.ts +165 -0
- package/core/websocket/explorer.ts +126 -0
- package/core/websocket/index.ts +78 -0
- package/core/websocket/middleware.ts +146 -0
- package/core/websocket/packet-codec.ts +75 -0
- package/core/websocket/reliable-delivery.ts +56 -0
- package/core/websocket/session-creation.ts +16 -0
- package/core/websocket/session-manager.ts +856 -0
- package/core/websocket/socket-wrapper.ts +314 -0
- package/core/websocket/topic-cache.ts +59 -0
- package/core/websocket/types.ts +122 -0
- package/core/websocket/websocketModule.ts +96 -0
- package/core/websocket/ws-dispatch.ts +123 -0
- package/core/websocket/ws-server.ts +1707 -0
- package/index.ts +281 -0
- package/library/boundary/diagnostics-v1.ts +136 -0
- package/library/boundary/index.ts +73 -0
- package/library/boundary/json/decodeBoundedJsonV1.ts +518 -0
- package/library/boundary/json/limits-v1.ts +46 -0
- package/library/boundary/json/normalizeBoundedJsonV1.ts +256 -0
- package/library/boundary/json/types-v1.ts +11 -0
- package/library/boundary/schema/boundarySchemaHashV1.ts +6 -0
- package/library/boundary/schema/collectBoundaryValueDiagnosticsV1.ts +325 -0
- package/library/boundary/schema/decodeBoundarySchemaV1.ts +646 -0
- package/library/boundary/schema/index.ts +8 -0
- package/library/boundary/schema/types-v1.ts +99 -0
- package/library/boundary/schema/validateBoundaryValueV1.ts +58 -0
- package/library/boundary/serialization/canonicalJsonV1.ts +66 -0
- package/library/http-client/HttpClient.ts +969 -0
- package/library/http-client/HttpClientFactory.ts +45 -0
- package/library/http-client/errors.ts +68 -0
- package/library/http-client/index.ts +43 -0
- package/library/http-client/interceptors.ts +40 -0
- package/library/http-client/progress.ts +62 -0
- package/library/http-client/redirectProtocol.ts +6 -0
- package/library/http-client/serialize.ts +133 -0
- package/library/http-client/types.ts +174 -0
- package/library/jsonapi/ListQueryError.ts +25 -0
- package/library/jsonapi/ListRequest.ts +37 -0
- package/library/jsonapi/decorators.ts +161 -0
- package/library/jsonapi/document.ts +124 -0
- package/library/jsonapi/index.ts +40 -0
- package/library/jsonapi/parseListQuery.ts +291 -0
- package/library/jsonapi/types.ts +125 -0
- package/library/jwt/JwtEncoder.ts +40 -0
- package/library/jwt/JwtKeyRing.ts +164 -0
- package/library/jwt/JwtValidator.ts +210 -0
- package/library/jwt/TokenIssuer.ts +149 -0
- package/library/jwt/TokenService.ts +51 -0
- package/library/jwt/base64url.ts +61 -0
- package/library/jwt/claims.ts +36 -0
- package/library/jwt/errors.ts +44 -0
- package/library/jwt/index.ts +59 -0
- package/library/jwt/limits.ts +8 -0
- package/library/jwt/signing/Hs256Algorithm.ts +62 -0
- package/library/jwt/signing/Rs256Algorithm.ts +133 -0
- package/library/jwt/signing/SigningAlgorithm.ts +18 -0
- package/library/jwt/signing/pem.ts +30 -0
- package/library/openapi/codegen.ts +875 -0
- package/library/openapi/document.ts +326 -0
- package/library/openapi/index.ts +13 -0
- package/library/openapi/types.ts +69 -0
- package/library/openapi/ui.ts +182 -0
- package/library/orm/DatabaseFacade.ts +209 -0
- package/library/orm/DbContext.ts +107 -0
- package/library/orm/DbContextFactory.ts +25 -0
- package/library/orm/DbContextOptions.ts +33 -0
- package/library/orm/Metadata/DynamicModelBuilder.ts +497 -0
- package/library/orm/Metadata/KeyTuple.ts +36 -0
- package/library/orm/Metadata/ModelBuilder.ts +299 -0
- package/library/orm/Metadata/OrmModel.ts +80 -0
- package/library/orm/Metadata/ValueConverter.ts +57 -0
- package/library/orm/Metadata/conventions.ts +54 -0
- package/library/orm/Metadata/decorators.ts +396 -0
- package/library/orm/Metadata/types.ts +140 -0
- package/library/orm/Providers/OwnedStoreCatalog.reader.ts +1802 -0
- package/library/orm/Providers/PostgresDialect.ts +234 -0
- package/library/orm/Providers/PostgresProvider.ts +1494 -0
- package/library/orm/Providers/PostgresSchema.decoder.ts +107 -0
- package/library/orm/Providers/limits.ts +29 -0
- package/library/orm/Providers/operationDeadline.ts +43 -0
- package/library/orm/Providers/ormOwnedStoreRuntime.ts +19 -0
- package/library/orm/Providers/ormTransactionRuntime.ts +117 -0
- package/library/orm/Providers/propertyConversion.ts +14 -0
- package/library/orm/Providers/resolvedForeignKey.ts +16 -0
- package/library/orm/Providers/transactionCallbacks.ts +45 -0
- package/library/orm/Providers/transactionOutcome.ts +82 -0
- package/library/orm/Providers/transactionScopes.ts +78 -0
- package/library/orm/Providers/types.ts +207 -0
- package/library/orm/Query/DbSet.ts +78 -0
- package/library/orm/Query/EntityQuery.ts +247 -0
- package/library/orm/Query/ImmediateMutations.ts +226 -0
- package/library/orm/Query/IncludeLoader.ts +200 -0
- package/library/orm/Query/QueryPlan.ts +55 -0
- package/library/orm/Query/SqlTranslator.ts +195 -0
- package/library/orm/Query/conditions.ts +127 -0
- package/library/orm/Query/materialize.ts +39 -0
- package/library/orm/README.md +256 -0
- package/library/orm/Repository/README.md +684 -0
- package/library/orm/Repository/Repository.ts +68 -0
- package/library/orm/Saving/CommandBuilder.ts +139 -0
- package/library/orm/Saving/ExecutionStrategy.ts +128 -0
- package/library/orm/Saving/SaveExecutor.ts +413 -0
- package/library/orm/Saving/applyConventions.ts +64 -0
- package/library/orm/Schema/CheckExpression.ts +327 -0
- package/library/orm/Schema/ExactSchemaVerifier.ts +168 -0
- package/library/orm/Schema/ExpectedSchema.ts +43 -0
- package/library/orm/Schema/MigrationRunner.ts +146 -0
- package/library/orm/Schema/Migrator.ts +73 -0
- package/library/orm/Schema/OrmOwnedStore.ts +123 -0
- package/library/orm/Schema/OwnedStoreAdmission.ts +752 -0
- package/library/orm/Schema/OwnedStoreCanonical.ts +273 -0
- package/library/orm/Schema/OwnedStoreCatalog.ts +1325 -0
- package/library/orm/Schema/SafeAdditiveSchema.ts +100 -0
- package/library/orm/Schema/SchemaAdmission.ts +62 -0
- package/library/orm/Schema/SchemaDiffer.ts +78 -0
- package/library/orm/Schema/formatSchemaDifferences.ts +62 -0
- package/library/orm/Schema/introspection.ts +52 -0
- package/library/orm/Schema/physicalColumnTypes.ts +37 -0
- package/library/orm/Schema/tableKey.ts +26 -0
- package/library/orm/Tracking/ChangeTracker.ts +448 -0
- package/library/orm/Tracking/EntityState.ts +13 -0
- package/library/orm/Transactions/OrmTransaction.ts +30 -0
- package/library/orm/Transactions/TransactionScopeCoordinator.ts +377 -0
- package/library/orm/errors.ts +190 -0
- package/library/orm/index.ts +162 -0
- package/library/orm/runtime.ts +14 -0
- package/library/redaction/index.ts +166 -0
- package/library/ui/UiProfile.ts +77 -0
- package/library/ui/compiled-v1.ts +131 -0
- package/library/ui/compiler/compileUiSurfaceV1.ts +717 -0
- package/library/ui/compiler/contracts-v1.ts +25 -0
- package/library/ui/compiler/index.ts +12 -0
- package/library/ui/compiler/openApiIndex.ts +246 -0
- package/library/ui/defineUiProfile.ts +340 -0
- package/library/ui/diagnostics-v1.ts +33 -0
- package/library/ui/index.ts +129 -0
- package/library/ui/profile-v1.ts +191 -0
- package/library/ui/serialization.ts +130 -0
- package/library/ui/uiProfileAuthoring.ts +289 -0
- package/library/ui/uiProfileAuthoringMetadata.ts +78 -0
- package/library/validation/MessageRegistry.ts +144 -0
- package/library/validation/README.md +62 -0
- package/library/validation/RuleCompiler.ts +183 -0
- package/library/validation/RuleEngine.ts +401 -0
- package/library/validation/SPEC.md +579 -0
- package/library/validation/ValidationError.ts +37 -0
- package/library/validation/ValidationResult.ts +63 -0
- package/library/validation/Validator.ts +101 -0
- package/library/validation/index.ts +16 -0
- package/library/validation/metadata.ts +69 -0
- package/library/validation/modelValidatorAdapter.ts +119 -0
- package/library/validation/types/ValidationCode.ts +69 -0
- package/library/validation/types/ValidatorOptions.ts +153 -0
- package/package.json +80 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { canonicalBoundaryJsonV1 as libraryCanonicalBoundaryJsonV1, canonicalJsonHashV1, decodeBoundedJsonV1, normalizeBoundedJsonV1 } from "../../../library/boundary";
|
|
2
|
+
import { AgentSessionError } from "./contracts";
|
|
3
|
+
|
|
4
|
+
const MARKER = "bazis.agent-session/plaintext/v1";
|
|
5
|
+
const VERSION = "bazis.agent-session/checkpoint/v1";
|
|
6
|
+
export const MAX_CHECKPOINT_BYTES_V1 = 2 * 1024 * 1024;
|
|
7
|
+
|
|
8
|
+
function fail(code: "AGENT_SESSION_INVALID_REQUEST" | "AGENT_SESSION_CHECKPOINT_CORRUPT" | "AGENT_SESSION_LIMIT_EXCEEDED"): never { throw new AgentSessionError(code); }
|
|
9
|
+
function closed(value: unknown, keys: readonly string[]): Record<string, unknown> {
|
|
10
|
+
const normalized = normalizeBoundedJsonV1(value);
|
|
11
|
+
if (!normalized.ok || value === null || typeof value !== "object" || Array.isArray(value) || Object.keys(value as object).sort().join(",") !== [...keys].sort().join(",")) fail("AGENT_SESSION_CHECKPOINT_CORRUPT");
|
|
12
|
+
return normalized.value as Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
function decode(text: string): unknown { const decoded = decodeBoundedJsonV1(text); if (!decoded.ok) fail("AGENT_SESSION_CHECKPOINT_CORRUPT"); return decoded.value; }
|
|
15
|
+
export function canonicalBoundaryJsonV1(value: unknown): string { try { return libraryCanonicalBoundaryJsonV1(value); } catch { return fail("AGENT_SESSION_INVALID_REQUEST"); } }
|
|
16
|
+
export function sessionDigestV1(domain: string, value: unknown): string { try { return canonicalJsonHashV1(domain, value); } catch { return fail("AGENT_SESSION_INVALID_REQUEST"); } }
|
|
17
|
+
export function sealedCheckpointEnvelopeV1(request: { readonly sessionId: string; readonly checkpointRevision: number; readonly bindingHash: string; readonly canonicalCheckpointJson: string }): string {
|
|
18
|
+
if (!/^[0-9a-f-]{36}$/i.test(request.sessionId) || !Number.isSafeInteger(request.checkpointRevision) || request.checkpointRevision < 0 || !/^(sha256:)?[0-9a-f]{64}$/.test(request.bindingHash)) fail("AGENT_SESSION_INVALID_REQUEST");
|
|
19
|
+
const checkpoint = decode(request.canonicalCheckpointJson);
|
|
20
|
+
// Raw JSON admission preserves duplicate-key evidence; only the exact output
|
|
21
|
+
// of the shared canonical serializer is accepted as a checkpoint boundary.
|
|
22
|
+
if (canonicalBoundaryJsonV1(checkpoint) !== request.canonicalCheckpointJson) fail("AGENT_SESSION_INVALID_REQUEST");
|
|
23
|
+
const envelope = { marker: MARKER, version: VERSION, sessionId: request.sessionId, checkpointRevision: request.checkpointRevision, bindingHash: request.bindingHash, checkpointDigest: sessionDigestV1(VERSION, checkpoint), checkpoint };
|
|
24
|
+
const result = canonicalBoundaryJsonV1(envelope);
|
|
25
|
+
if (Buffer.byteLength(result) > MAX_CHECKPOINT_BYTES_V1) fail("AGENT_SESSION_LIMIT_EXCEEDED");
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
export function openSealedCheckpointEnvelopeV1(text: string, expected: { readonly sessionId: string; readonly checkpointRevision: number; readonly bindingHash: string }): string {
|
|
29
|
+
if (Buffer.byteLength(text) > MAX_CHECKPOINT_BYTES_V1) fail("AGENT_SESSION_CHECKPOINT_CORRUPT");
|
|
30
|
+
const envelope = closed(decode(text), ["marker", "version", "sessionId", "checkpointRevision", "bindingHash", "checkpointDigest", "checkpoint"]);
|
|
31
|
+
if (envelope.marker !== MARKER || envelope.version !== VERSION || envelope.sessionId !== expected.sessionId || envelope.checkpointRevision !== expected.checkpointRevision || envelope.bindingHash !== expected.bindingHash || typeof envelope.checkpointDigest !== "string" || envelope.checkpointDigest !== sessionDigestV1(VERSION, envelope.checkpoint) || canonicalBoundaryJsonV1(envelope) !== text) fail("AGENT_SESSION_CHECKPOINT_CORRUPT");
|
|
32
|
+
return canonicalBoundaryJsonV1(envelope.checkpoint);
|
|
33
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Secret } from "../../kernel";
|
|
2
|
+
import type { BazisModuleRef } from "../../di";
|
|
3
|
+
import type { AgentToolExecutorOptions, AgentToolSchemaValidator } from "../AgentToolExecutor";
|
|
4
|
+
import { normalizeJsonValue, type JsonObject, type JsonValue } from "../semantic";
|
|
5
|
+
import { Validator } from "../../../library/validation";
|
|
6
|
+
|
|
7
|
+
const UUID_V1_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
8
|
+
|
|
9
|
+
export interface AgentSessionPrincipalV1 { readonly subject: string; readonly tenant?: string; }
|
|
10
|
+
export interface AgentSessionCallContextV1 { readonly principal: AgentSessionPrincipalV1; readonly signal?: AbortSignal; }
|
|
11
|
+
|
|
12
|
+
export class CreateAgentSessionRequestV1 {
|
|
13
|
+
@Validator({ required: true, pattern: UUID_V1_PATTERN })
|
|
14
|
+
sessionId!: string;
|
|
15
|
+
@Validator({ required: true, pattern: UUID_V1_PATTERN })
|
|
16
|
+
requestId!: string;
|
|
17
|
+
@Validator({ required: true, minLength: 1, maxLength: 128 })
|
|
18
|
+
agentName!: string;
|
|
19
|
+
@Validator({ minLength: 1, maxLength: 128 })
|
|
20
|
+
taskName?: string;
|
|
21
|
+
@Validator({
|
|
22
|
+
required: true,
|
|
23
|
+
// JsonValue deliberately includes null. Keep absence invalid while
|
|
24
|
+
// allowing that exact JSON literal through the existing Validator flow.
|
|
25
|
+
validateIf: (instance) => (instance as CreateAgentSessionRequestV1).input !== null,
|
|
26
|
+
custom: (value) => {
|
|
27
|
+
try {
|
|
28
|
+
normalizeJsonValue(value, "agentSession.input");
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
input!: JsonValue;
|
|
36
|
+
@Validator({ minLength: 1, maxLength: 128 })
|
|
37
|
+
modelProfile?: string;
|
|
38
|
+
@Validator({ min: 1, max: 64, integer: true })
|
|
39
|
+
maxSteps?: number;
|
|
40
|
+
@Validator({ min: 1, max: 64, integer: true })
|
|
41
|
+
maxToolCallsPerStep?: number;
|
|
42
|
+
@Validator({ min: 1, max: 900000, integer: true })
|
|
43
|
+
runTimeoutMs?: number;
|
|
44
|
+
}
|
|
45
|
+
export class RunAgentSessionRequestV1 {
|
|
46
|
+
@Validator({ required: true, pattern: UUID_V1_PATTERN }) sessionId!: string;
|
|
47
|
+
@Validator({ required: true, pattern: UUID_V1_PATTERN }) commandId!: string;
|
|
48
|
+
}
|
|
49
|
+
export class ReadAgentSessionRequestV1 { @Validator({ required: true, pattern: UUID_V1_PATTERN }) sessionId!: string; }
|
|
50
|
+
export class StopAgentSessionRequestV1 { @Validator({ required: true, pattern: UUID_V1_PATTERN }) sessionId!: string; @Validator({ required: true, pattern: UUID_V1_PATTERN }) commandId!: string; }
|
|
51
|
+
export class ResumeAgentSessionRequestV1 { @Validator({ required: true, pattern: UUID_V1_PATTERN }) sessionId!: string; @Validator({ required: true, pattern: UUID_V1_PATTERN }) commandId!: string; }
|
|
52
|
+
export class ReadAgentSessionEventsRequestV1 { @Validator({ required: true, pattern: UUID_V1_PATTERN }) sessionId!: string; after?: AgentSessionCursorV1; @Validator({ min: 1, max: 500, integer: true }) limit?: number; }
|
|
53
|
+
|
|
54
|
+
export type AgentSessionStateV1 = "created" | "running" | "stop-requested" | "stopped" | "completed" | "failed" | "outcome-unknown";
|
|
55
|
+
export type AgentSessionCursorV1 = string;
|
|
56
|
+
export interface AgentSessionOutcomeV1 { readonly status: "completed" | "failed" | "outcome-unknown"; readonly finalText?: string; readonly output?: JsonValue; readonly error?: { readonly code: string; readonly message: string }; }
|
|
57
|
+
export interface AgentSessionViewV1 {
|
|
58
|
+
readonly version: 1; readonly sessionId: string; readonly invocationId: string; readonly agentName: string; readonly taskName?: string;
|
|
59
|
+
readonly tenant?: string; readonly state: AgentSessionStateV1; readonly revision: number; readonly steps: number; readonly stopRequested: boolean;
|
|
60
|
+
readonly resumeAllowed: boolean; readonly createdAt: string; readonly updatedAt: string; readonly outcome?: AgentSessionOutcomeV1;
|
|
61
|
+
}
|
|
62
|
+
export interface AgentSessionRunResultV1 { readonly session: AgentSessionViewV1; }
|
|
63
|
+
export interface AgentSessionStopResultV1 { readonly disposition: "requested" | "already-stopped" | "already-terminal"; readonly session: AgentSessionViewV1; }
|
|
64
|
+
export type AgentSessionEventKindV1 = "session-created" | "run-started" | "owner-reclaimed" | "model-dispatch-intent" | "model-result" | "tool-dispatch-intent" | "tool-result" | "stop-requested" | "stopped" | "completed" | "failed" | "outcome-unknown";
|
|
65
|
+
export interface AgentSessionEventV1 { readonly version: 1; readonly eventId: string; readonly sessionId: string; readonly sequence: number; readonly kind: AgentSessionEventKindV1; readonly occurredAt: string; readonly projection: JsonObject; }
|
|
66
|
+
export interface AgentSessionEventPageV1 { readonly items: readonly AgentSessionEventV1[]; readonly nextCursor: AgentSessionCursorV1; readonly hasMore: boolean; }
|
|
67
|
+
|
|
68
|
+
export abstract class AgentSessions {
|
|
69
|
+
abstract create(request: CreateAgentSessionRequestV1, context: AgentSessionCallContextV1): Promise<AgentSessionViewV1>;
|
|
70
|
+
abstract run(request: RunAgentSessionRequestV1, context: AgentSessionCallContextV1): Promise<AgentSessionRunResultV1>;
|
|
71
|
+
abstract read(request: ReadAgentSessionRequestV1, context: AgentSessionCallContextV1): Promise<AgentSessionViewV1>;
|
|
72
|
+
abstract stop(request: StopAgentSessionRequestV1, context: AgentSessionCallContextV1): Promise<AgentSessionStopResultV1>;
|
|
73
|
+
abstract resume(request: ResumeAgentSessionRequestV1, context: AgentSessionCallContextV1): Promise<AgentSessionRunResultV1>;
|
|
74
|
+
abstract readEvents(request: ReadAgentSessionEventsRequestV1, context: AgentSessionCallContextV1): Promise<AgentSessionEventPageV1>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface AgentSessionAuthorizationTargetV1 { readonly sessionId: string; readonly ownerSubject: string; readonly tenant?: string; readonly agentName: string; readonly taskName?: string; }
|
|
78
|
+
export type AgentSessionAuthorizationRequestV1 =
|
|
79
|
+
| { readonly action: "create"; readonly principal: AgentSessionPrincipalV1; readonly candidate: AgentSessionAuthorizationTargetV1 }
|
|
80
|
+
| { readonly action: "run" | "read" | "read-events" | "stop" | "resume"; readonly principal: AgentSessionPrincipalV1; readonly session: AgentSessionAuthorizationTargetV1 & { readonly state: AgentSessionStateV1 } };
|
|
81
|
+
export abstract class AgentSessionAuthorizationPolicyV1 { abstract authorize(request: AgentSessionAuthorizationRequestV1): Promise<boolean>; }
|
|
82
|
+
|
|
83
|
+
export interface AgentSessionCheckpointProtectionConfigV1 { readonly activeKeyId: string; readonly readableKeyIds: readonly string[]; readonly keys: Readonly<Record<string, Secret>>; }
|
|
84
|
+
export interface AgentSessionSealRequestV1 { readonly sessionId: string; readonly checkpointRevision: number; readonly bindingHash: string; readonly canonicalCheckpointJson: string; }
|
|
85
|
+
export interface AgentSessionSealedCheckpointV1 { readonly envelopeVersion: "bazis.agent-session/sealed/v1"; readonly keyId: string; readonly ciphertext: string; }
|
|
86
|
+
export interface AgentSessionOpenRequestV1 { readonly expectedSessionId: string; readonly expectedCheckpointRevision: number; readonly expectedBindingHash: string; readonly sealed: AgentSessionSealedCheckpointV1; }
|
|
87
|
+
export abstract class AgentSessionCheckpointProtectorV1 { abstract seal(request: AgentSessionSealRequestV1): Promise<AgentSessionSealedCheckpointV1>; abstract open(request: AgentSessionOpenRequestV1): Promise<string>; }
|
|
88
|
+
|
|
89
|
+
export interface AgentSessionModuleOptionsV1 {
|
|
90
|
+
readonly imports?: readonly BazisModuleRef[]; readonly agentModules: readonly BazisModuleRef[]; readonly implementationVersion: string;
|
|
91
|
+
readonly admission: { readonly bucket: string; readonly maxActiveRuns?: number };
|
|
92
|
+
readonly execution?: { readonly providerCallTimeoutMs?: number; readonly taskSchemaValidator?: AgentToolSchemaValidator; readonly toolExecutorOptions?: Pick<AgentToolExecutorOptions, "approvalPolicy" | "schemaValidator" | "auditSink" | "defaultTimeoutMs" | "scopeDisposeTimeoutMs" | "requiredPlatformHooks" | "hookRedaction">; };
|
|
93
|
+
readonly limits?: { readonly runTimeoutMs?: number; readonly maxSessionSteps?: number; readonly maxToolCallsPerStep?: number; readonly ownerLeaseMs?: number; readonly ownerHeartbeatMs?: number; readonly ownerStopGraceMs?: number; readonly authorizationTimeoutMs?: number; readonly checkpointProtectionTimeoutMs?: number; readonly databaseLockTimeoutMs?: number; readonly databaseStatementTimeoutMs?: number; readonly databaseWaitTimeoutMs?: number; readonly stopCheckIntervalMs?: number; readonly maxInputBytes?: number; readonly maxCheckpointBytes?: number; readonly maxJournalPayloadBytes?: number; readonly maxJournalEntries?: number; readonly reservedControlJournalEntries?: number; readonly defaultJournalPageSize?: number; readonly maxJournalPageSize?: number; };
|
|
94
|
+
}
|
|
95
|
+
export type AgentSessionErrorCodeV1 = `AGENT_SESSION_${"INVALID_REQUEST" | "FORBIDDEN" | "NOT_FOUND" | "CONFLICT" | "OWNER_ACTIVE" | "ADMISSION_UNAVAILABLE" | "NOT_RESUMABLE" | "DEADLINE_EXCEEDED" | "LIMIT_EXCEEDED" | "AMBIENT_TRANSACTION_FORBIDDEN" | "BINDING_MISMATCH" | "CHECKPOINT_UNAVAILABLE" | "CHECKPOINT_CORRUPT" | "OUTCOME_UNKNOWN" | "STORE_CORRUPT" | "STORE_UNAVAILABLE" | "AUTHORIZATION_UNAVAILABLE" | "HOST_STOPPING" | "UNSUPPORTED_VERSION" | "IDEMPOTENCY_CONFLICT" | "COMMIT_OUTCOME_UNKNOWN" | "CONFIG_MISMATCH"}`;
|
|
96
|
+
export class AgentSessionError extends Error { constructor(readonly code: AgentSessionErrorCodeV1, readonly retryable = false) { super(code); this.name = "AgentSessionError"; } }
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Column, DbContext, Entity, Index, Key } from "../../../library/orm";
|
|
2
|
+
|
|
3
|
+
/** Immutable v1 schema. These tables are owned exclusively by AgentSessionDbContext. */
|
|
4
|
+
@Entity({ table: "bazis_agent_sessions_v1" })
|
|
5
|
+
@Index(["createKey"], { unique: true })
|
|
6
|
+
@Index(["sessionId"], { unique: true })
|
|
7
|
+
export class AgentSessionRowV1 {
|
|
8
|
+
@Key({ generated: false }) @Column({ type: "uuid" }) id = "";
|
|
9
|
+
@Column({ type: "uuid" }) sessionId = "";
|
|
10
|
+
@Column({ type: "uuid" }) invocationId = "";
|
|
11
|
+
@Column({ type: "text" }) createKey = "";
|
|
12
|
+
@Column({ type: "text" }) requestBinding = "";
|
|
13
|
+
@Column({ type: "text" }) ownerSubject = "";
|
|
14
|
+
@Column({ type: "text", nullable: true }) tenant?: string;
|
|
15
|
+
@Column({ type: "text" }) agentName = "";
|
|
16
|
+
@Column({ type: "text", nullable: true }) taskName?: string;
|
|
17
|
+
@Column({ type: "text" }) implementationVersion = "";
|
|
18
|
+
@Column({ type: "text" }) bindingHash = "";
|
|
19
|
+
@Column({ type: "text" }) state = "created";
|
|
20
|
+
@Column({ type: "integer" }) revision = 0;
|
|
21
|
+
@Column({ type: "integer" }) steps = 0;
|
|
22
|
+
@Column({ type: "boolean" }) stopRequested = false;
|
|
23
|
+
@Column({ type: "integer" }) checkpointRevision = 0;
|
|
24
|
+
@Column({ type: "text", nullable: true }) ownerId?: string;
|
|
25
|
+
@Column({ type: "integer" }) ownerEpoch = 0;
|
|
26
|
+
@Column({ type: "datetime", nullable: true }) ownerLeaseUntil?: Date;
|
|
27
|
+
@Column({ type: "text", nullable: true }) runCommandId?: string;
|
|
28
|
+
@Column({ type: "datetime", nullable: true }) runDeadline?: Date;
|
|
29
|
+
@Column({ type: "integer" }) nextSequence = 1;
|
|
30
|
+
@Column({ type: "integer", nullable: true }) pendingIntentSequence?: number;
|
|
31
|
+
@Column({ type: "boolean" }) admissionReserved = false;
|
|
32
|
+
@Column({ type: "datetime" }) createdAt = new Date();
|
|
33
|
+
@Column({ type: "datetime" }) updatedAt = new Date();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Entity({ table: "bazis_agent_session_checkpoints_v1" })
|
|
37
|
+
@Index(["sessionId", "checkpointRevision"], { unique: true })
|
|
38
|
+
export class AgentSessionCheckpointRowV1 {
|
|
39
|
+
@Key({ generated: false }) @Column({ type: "uuid" }) id = "";
|
|
40
|
+
@Column({ type: "uuid" }) sessionId = "";
|
|
41
|
+
@Column({ type: "integer" }) checkpointRevision = 0;
|
|
42
|
+
@Column({ type: "text" }) bindingHash = "";
|
|
43
|
+
@Column({ type: "text" }) keyId = "";
|
|
44
|
+
@Column({ type: "text" }) ciphertext = "";
|
|
45
|
+
@Column({ type: "datetime" }) createdAt = new Date();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Entity({ table: "bazis_agent_session_journal_v1" })
|
|
49
|
+
@Index(["sessionId", "sequence"], { unique: true })
|
|
50
|
+
@Index(["sessionId", "commandId"], { unique: false })
|
|
51
|
+
export class AgentSessionJournalRowV1 {
|
|
52
|
+
@Key({ generated: false }) @Column({ type: "uuid" }) id = "";
|
|
53
|
+
@Column({ type: "uuid" }) eventId = "";
|
|
54
|
+
@Column({ type: "uuid" }) sessionId = "";
|
|
55
|
+
@Column({ type: "integer" }) sequence = 0;
|
|
56
|
+
@Column({ type: "integer" }) aggregateRevision = 0;
|
|
57
|
+
@Column({ type: "text" }) kind = "";
|
|
58
|
+
@Column({ type: "text", nullable: true }) commandId?: string;
|
|
59
|
+
@Column({ type: "text" }) projectionJson = "{}";
|
|
60
|
+
@Column({ type: "text", nullable: true }) binding?: string;
|
|
61
|
+
@Column({ type: "datetime" }) occurredAt = new Date();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Entity({ table: "bazis_agent_session_admission_v1" })
|
|
65
|
+
@Index(["bucket"], { unique: true })
|
|
66
|
+
export class AgentSessionAdmissionRowV1 {
|
|
67
|
+
@Key({ generated: false }) @Column({ type: "uuid" }) id = "";
|
|
68
|
+
@Column({ type: "text" }) bucket = "";
|
|
69
|
+
@Column({ type: "text" }) configHash = "";
|
|
70
|
+
@Column({ type: "integer" }) maxActiveRuns = 8;
|
|
71
|
+
@Column({ type: "integer" }) activeReservations = 0;
|
|
72
|
+
@Column({ type: "datetime" }) updatedAt = new Date();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class AgentSessionDbContext extends DbContext {
|
|
76
|
+
readonly sessions = this.set(AgentSessionRowV1);
|
|
77
|
+
readonly checkpoints = this.set(AgentSessionCheckpointRowV1);
|
|
78
|
+
readonly journal = this.set(AgentSessionJournalRowV1);
|
|
79
|
+
readonly admission = this.set(AgentSessionAdmissionRowV1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const AGENT_SESSION_ENTITIES_V1 = Object.freeze([
|
|
83
|
+
AgentSessionRowV1, AgentSessionCheckpointRowV1, AgentSessionJournalRowV1, AgentSessionAdmissionRowV1,
|
|
84
|
+
] as const);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createToken } from "../../di";
|
|
2
|
+
import { reader, type InfraConnector } from "../../infra";
|
|
3
|
+
import { type AppConfig, type ConfigRegistry, Secret } from "../../kernel";
|
|
4
|
+
import { ValueConverters, type ValueConverter } from "../../../library/orm";
|
|
5
|
+
import { types as nodeUtilTypes } from "node:util";
|
|
6
|
+
import { AgentSessionError, type AgentSessionCheckpointProtectionConfigV1, type AgentSessionCheckpointProtectorV1, type AgentSessionOpenRequestV1, type AgentSessionSealRequestV1, type AgentSessionSealedCheckpointV1 } from "./contracts";
|
|
7
|
+
import { openSealedCheckpointEnvelopeV1, sealedCheckpointEnvelopeV1 } from "./codec";
|
|
8
|
+
import { identifyConnector } from "../../infra/connectorIdentity";
|
|
9
|
+
|
|
10
|
+
export const AGENT_SESSION_CHECKPOINT_PROTECTOR = createToken<AgentSessionCheckpointProtectorV1>("AgentSessionCheckpointProtectorV1");
|
|
11
|
+
|
|
12
|
+
function closedDataRecord(value: unknown, keys: readonly string[]): Record<string, unknown> | undefined {
|
|
13
|
+
if (typeof value !== "object" || value === null || nodeUtilTypes.isProxy(value)) return undefined;
|
|
14
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) return undefined;
|
|
15
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
16
|
+
if (ownKeys.length !== keys.length || ownKeys.some((key) => typeof key !== "string" || !keys.includes(key))) return undefined;
|
|
17
|
+
const result: Record<string, unknown> = Object.create(null);
|
|
18
|
+
for (const key of keys) {
|
|
19
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
20
|
+
if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) return undefined;
|
|
21
|
+
result[key] = descriptor.value;
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function closedStringArray(value: unknown): readonly string[] | undefined {
|
|
27
|
+
if (!Array.isArray(value) || nodeUtilTypes.isProxy(value)) return undefined;
|
|
28
|
+
if (Reflect.ownKeys(value).some((key) => key !== "length" && (typeof key !== "string" || !/^(0|[1-9][0-9]*)$/.test(key)))) return undefined;
|
|
29
|
+
const result: string[] = [];
|
|
30
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
31
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
32
|
+
if (!descriptor || !descriptor.enumerable || !("value" in descriptor) || typeof descriptor.value !== "string") return undefined;
|
|
33
|
+
result.push(descriptor.value);
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function snapshot(config: AppConfig<AgentSessionCheckpointProtectionConfigV1>) {
|
|
39
|
+
const values = reader(config); const activeKeyId = values.get("activeKeyId"); const readableKeyIds = values.get("readableKeyIds"); const keys = values.get("keys");
|
|
40
|
+
const readable = closedStringArray(readableKeyIds);
|
|
41
|
+
if (typeof activeKeyId !== "string" || !activeKeyId || !readable || !keys || typeof keys !== "object" || nodeUtilTypes.isProxy(keys)) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
42
|
+
const keyRecord = keys as object;
|
|
43
|
+
if (Object.getPrototypeOf(keyRecord) !== Object.prototype || Reflect.ownKeys(keyRecord).some((key) => typeof key !== "string" || key === "__proto__" || key === "prototype" || key === "constructor")) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
44
|
+
for (const key of Reflect.ownKeys(keyRecord)) {
|
|
45
|
+
const descriptor = Object.getOwnPropertyDescriptor(keyRecord, key as string);
|
|
46
|
+
if (!descriptor || !descriptor.enumerable || descriptor.get || descriptor.set || !(descriptor.value instanceof Secret)) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
47
|
+
}
|
|
48
|
+
const converters = new Map<string, ValueConverter<string, string>>();
|
|
49
|
+
for (const id of readable) {
|
|
50
|
+
if (typeof id !== "string" || !id || converters.has(id)) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
51
|
+
const descriptor = Object.getOwnPropertyDescriptor(keyRecord, id);
|
|
52
|
+
if (!descriptor || descriptor.get || descriptor.set || !(descriptor.value instanceof Secret)) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
53
|
+
const secret = descriptor.value.reveal();
|
|
54
|
+
if (!secret) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
55
|
+
converters.set(id, ValueConverters.encrypted(secret));
|
|
56
|
+
}
|
|
57
|
+
if (!converters.has(activeKeyId)) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
58
|
+
return Object.freeze({ activeKeyId, readable: new Set(converters.keys()), converters });
|
|
59
|
+
}
|
|
60
|
+
class CheckpointProtector implements AgentSessionCheckpointProtectorV1 {
|
|
61
|
+
constructor(private readonly keys: ReturnType<typeof snapshot>) {}
|
|
62
|
+
async seal(request: AgentSessionSealRequestV1): Promise<AgentSessionSealedCheckpointV1> {
|
|
63
|
+
const input = closedDataRecord(request, ["sessionId", "checkpointRevision", "bindingHash", "canonicalCheckpointJson"]);
|
|
64
|
+
if (!input || typeof input.sessionId !== "string" || typeof input.checkpointRevision !== "number" || typeof input.bindingHash !== "string" || typeof input.canonicalCheckpointJson !== "string") throw new AgentSessionError("AGENT_SESSION_INVALID_REQUEST");
|
|
65
|
+
const converter = this.keys.converters.get(this.keys.activeKeyId);
|
|
66
|
+
if (!converter) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
67
|
+
const sealRequest: AgentSessionSealRequestV1 = {
|
|
68
|
+
sessionId: input.sessionId,
|
|
69
|
+
checkpointRevision: input.checkpointRevision,
|
|
70
|
+
bindingHash: input.bindingHash,
|
|
71
|
+
canonicalCheckpointJson: input.canonicalCheckpointJson,
|
|
72
|
+
};
|
|
73
|
+
return Object.freeze({ envelopeVersion: "bazis.agent-session/sealed/v1", keyId: this.keys.activeKeyId, ciphertext: converter.toProvider(sealedCheckpointEnvelopeV1(sealRequest)) });
|
|
74
|
+
}
|
|
75
|
+
async open(request: AgentSessionOpenRequestV1): Promise<string> {
|
|
76
|
+
const input = closedDataRecord(request, ["expectedSessionId", "expectedCheckpointRevision", "expectedBindingHash", "sealed"]);
|
|
77
|
+
const sealed = input === undefined ? undefined : closedDataRecord(input.sealed, ["envelopeVersion", "keyId", "ciphertext"]);
|
|
78
|
+
if (!input || !sealed || typeof input.expectedSessionId !== "string" || typeof input.expectedCheckpointRevision !== "number" || typeof input.expectedBindingHash !== "string" || sealed.envelopeVersion !== "bazis.agent-session/sealed/v1" || typeof sealed.keyId !== "string" || typeof sealed.ciphertext !== "string" || !this.keys.readable.has(sealed.keyId)) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
79
|
+
const converter = this.keys.converters.get(sealed.keyId);
|
|
80
|
+
if (!converter) throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_UNAVAILABLE");
|
|
81
|
+
try { return openSealedCheckpointEnvelopeV1(converter.fromProvider(sealed.ciphertext), { sessionId: input.expectedSessionId, checkpointRevision: input.expectedCheckpointRevision, bindingHash: input.expectedBindingHash }); } catch (error) { if (error instanceof AgentSessionError) throw error; throw new AgentSessionError("AGENT_SESSION_CHECKPOINT_CORRUPT"); }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export function agentSessionCheckpointProtection(config: AppConfig<AgentSessionCheckpointProtectionConfigV1>): InfraConnector<AgentSessionCheckpointProtectorV1> {
|
|
85
|
+
return identifyConnector(Object.freeze({
|
|
86
|
+
token: AGENT_SESSION_CHECKPOINT_PROTECTOR,
|
|
87
|
+
config,
|
|
88
|
+
create: (configs?: ConfigRegistry) => new CheckpointProtector(snapshot(configs?.get(config) ?? config)),
|
|
89
|
+
connect: () => undefined,
|
|
90
|
+
dispose: () => undefined,
|
|
91
|
+
}), "agent-session-checkpoint-protection");
|
|
92
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Composition layer: the single application entry point. Depends on the kernel, HTTP, gRPC and
|
|
2
|
+
// the validation library (it is the composition root, so it may use everything), hiding
|
|
3
|
+
// infrastructure wiring from application code.
|
|
4
|
+
export { runApp, type RunAppOptions } from "./runApp";
|
|
5
|
+
export * from "./ui";
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectModuleUiProfiles,
|
|
3
|
+
collectModuleControllers,
|
|
4
|
+
DI,
|
|
5
|
+
Global,
|
|
6
|
+
Module,
|
|
7
|
+
singletonValue,
|
|
8
|
+
type BazisModuleRef,
|
|
9
|
+
} from "../di";
|
|
10
|
+
import { loadBazisGeneratedRuntime } from "../generatedRuntime";
|
|
11
|
+
import { httpModule, useModelValidator, type HttpModuleOptions, type ModelValidator } from "../http";
|
|
12
|
+
import { grpcModule, type GrpcModuleOptions } from "../grpc";
|
|
13
|
+
import { buildHttpOpenApiDocument } from "../http/OpenApi/openApiDocument";
|
|
14
|
+
import { KernelBuilder, Bazis, type KernelOptions, type ValidatableConfig } from "../kernel";
|
|
15
|
+
import {
|
|
16
|
+
isUiProfileAuthoringClass,
|
|
17
|
+
type UiProfileV1,
|
|
18
|
+
} from "../../library/ui";
|
|
19
|
+
import { modelValidatorAdapter } from "../../library/validation";
|
|
20
|
+
import {
|
|
21
|
+
type RunAppUiOptions,
|
|
22
|
+
type RunAppUiSurfaceOptions,
|
|
23
|
+
type UiSurfaceHostingOptions,
|
|
24
|
+
} from "./ui/uiSurfaceHosting";
|
|
25
|
+
import { resolveUiProfileAuthoringV1, UiProfileV1Registry, type UiLabels } from "./ui/uiProfileResolver";
|
|
26
|
+
import { UiSurfaceDocumentProvider, UiSurfaceHttpController } from "./ui/uiSurfaceHttp";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Application start options. Everything is optional: without `http` and `grpc` the app
|
|
30
|
+
* starts as a worker/CLI (kernel and hosted services only).
|
|
31
|
+
*/
|
|
32
|
+
export interface RunAppOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Start the HTTP server. Controllers are collected from the whole module tree
|
|
35
|
+
* automatically, no need to list them. Pass `{}` for the defaults
|
|
36
|
+
* (port 3000) or an object with settings (port/prefix/cors/...).
|
|
37
|
+
*/
|
|
38
|
+
readonly http?: HttpModuleOptions;
|
|
39
|
+
/** gRPC server; discovers feature-module grpcControllers, independently of HTTP. */
|
|
40
|
+
readonly grpc?: GrpcModuleOptions;
|
|
41
|
+
/** Kernel options (environment, shutdown timeout, signals, ...). */
|
|
42
|
+
readonly kernel?: KernelOptions;
|
|
43
|
+
/**
|
|
44
|
+
* Request-model validator. The `@/library/validation` engine is used by
|
|
45
|
+
* default. Pass your own to replace it.
|
|
46
|
+
*/
|
|
47
|
+
readonly validator?: ModelValidator;
|
|
48
|
+
/** Fine-tuning of the kernel builder (logger, config sources, ...). */
|
|
49
|
+
readonly configure?: (builder: KernelBuilder) => void;
|
|
50
|
+
/**
|
|
51
|
+
* Additional declarative configs (`defineConfig`) that do not belong to a
|
|
52
|
+
* specific module. Usually configs live next to their owner: `@Infra` brings
|
|
53
|
+
* connector configs, and a feature module brings its own `config`.
|
|
54
|
+
* Every config is checked at startup (fail-fast): missing secrets and
|
|
55
|
+
* invalid values stop the start immediately.
|
|
56
|
+
*/
|
|
57
|
+
readonly config?: ValidatableConfig | readonly ValidatableConfig[];
|
|
58
|
+
/**
|
|
59
|
+
* Infrastructure manifest: a class with `@Infra` (or the result of `infraModule(...)`).
|
|
60
|
+
* It is a global module with connectors (DB/cache/search): clients are registered under
|
|
61
|
+
* their tokens, connections open before the servers and close after them.
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* await runApp(AppModule, { infra: AppInfra, http: { port: 3000 } });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
readonly infra?: BazisModuleRef;
|
|
68
|
+
/**
|
|
69
|
+
* Application cache as a self-installing value. Pass `memory({ ... })` for
|
|
70
|
+
* an in-memory cache. The distributed Redis backend is enabled separately via
|
|
71
|
+
* `infra: AppInfra` (`redisConnect(redisConfig, { cache: "distributed" })`).
|
|
72
|
+
* Registers `ICache`, enables `@OutputCache`/`@Cacheable` and a health check.
|
|
73
|
+
*
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { memory } from "@/core/cache";
|
|
76
|
+
* await runApp(AppModule, { cache: memory({ maxEntries: 1000 }), http: {} });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
readonly cache?: BazisModuleRef;
|
|
80
|
+
/**
|
|
81
|
+
* Declarative UI surface hosting. Feature modules contribute reference-based
|
|
82
|
+
* `@UiProfile` declarations through module `uiProfiles` metadata. Explicit
|
|
83
|
+
* surfaces expose protected `/ui/:surface`, `/openapi` and `/session`
|
|
84
|
+
* endpoints. Every published surface must provide authorization, a monotonic
|
|
85
|
+
* policy projection and a safe session mapper.
|
|
86
|
+
*/
|
|
87
|
+
readonly ui?: RunAppUiOptions;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function withUiRuntime(
|
|
91
|
+
root: BazisModuleRef,
|
|
92
|
+
option: RunAppOptions["ui"],
|
|
93
|
+
http: HttpModuleOptions | undefined,
|
|
94
|
+
): BazisModuleRef {
|
|
95
|
+
const declarations = collectModuleUiProfiles([root]);
|
|
96
|
+
const openApi = http === undefined ? undefined : buildUiOpenApiDocument(root, http);
|
|
97
|
+
const profiles = resolveUiProfiles(root, declarations, http, openApi, option?.labels);
|
|
98
|
+
const profileRegistry = new UiProfileV1Registry(profiles, openApi);
|
|
99
|
+
const httpOptions = http === undefined ? undefined : normalizeUiSurfaceHostingOptions(option, http);
|
|
100
|
+
if (httpOptions === undefined || openApi === undefined) {
|
|
101
|
+
return root;
|
|
102
|
+
}
|
|
103
|
+
const surfaceDocuments = new UiSurfaceDocumentProvider(httpOptions, profileRegistry, openApi);
|
|
104
|
+
|
|
105
|
+
@Global()
|
|
106
|
+
@Module({
|
|
107
|
+
providers: [singletonValue(UiSurfaceDocumentProvider, surfaceDocuments)],
|
|
108
|
+
exports: [UiSurfaceDocumentProvider],
|
|
109
|
+
})
|
|
110
|
+
class BazisUiModule {}
|
|
111
|
+
|
|
112
|
+
@Module({
|
|
113
|
+
imports: [BazisUiModule],
|
|
114
|
+
controllers: [
|
|
115
|
+
DI.bindDeps(UiSurfaceHttpController, UiSurfaceDocumentProvider),
|
|
116
|
+
],
|
|
117
|
+
})
|
|
118
|
+
class BazisUiHttpModule {}
|
|
119
|
+
|
|
120
|
+
return { imports: [BazisUiModule, BazisUiHttpModule, root] };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** @internal Resolves module-owned `@UiProfile` declarations before DI wiring. */
|
|
124
|
+
export function resolveUiProfiles(
|
|
125
|
+
root: BazisModuleRef,
|
|
126
|
+
declarations: readonly unknown[],
|
|
127
|
+
http: HttpModuleOptions | undefined,
|
|
128
|
+
prebuiltOpenApi?: ReturnType<typeof buildHttpOpenApiDocument>,
|
|
129
|
+
labels?: UiLabels,
|
|
130
|
+
): readonly UiProfileV1[] {
|
|
131
|
+
const authoring: object[] = [];
|
|
132
|
+
for (const declaration of declarations) {
|
|
133
|
+
if (isUiProfileAuthoringClass(declaration)) {
|
|
134
|
+
authoring.push(declaration);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
throw new TypeError(
|
|
138
|
+
`uiProfiles declaration ${declarationName(declaration)} must use @UiProfile().`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
if (authoring.length === 0) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const openApi = prebuiltOpenApi ?? buildUiOpenApiDocument(root, http ?? {});
|
|
146
|
+
const profiles: UiProfileV1[] = [];
|
|
147
|
+
for (const declaration of authoring) {
|
|
148
|
+
const result = resolveUiProfileAuthoringV1({ declaration, openApi, labels });
|
|
149
|
+
if (!result.ok) {
|
|
150
|
+
const details = result.diagnostics
|
|
151
|
+
.map((diagnostic) => `${diagnostic.code}: ${diagnostic.message}`)
|
|
152
|
+
.join("\n");
|
|
153
|
+
throw new TypeError(`@UiProfile resolution failed:\n${details}`);
|
|
154
|
+
}
|
|
155
|
+
profiles.push(...result.profiles);
|
|
156
|
+
}
|
|
157
|
+
return Object.freeze(profiles);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function buildUiOpenApiDocument(
|
|
161
|
+
root: BazisModuleRef,
|
|
162
|
+
http: HttpModuleOptions,
|
|
163
|
+
): ReturnType<typeof buildHttpOpenApiDocument> {
|
|
164
|
+
const docs = typeof http.docs === "object" && http.docs !== null ? http.docs : undefined;
|
|
165
|
+
return buildHttpOpenApiDocument({
|
|
166
|
+
controllers: collectModuleControllers([root]),
|
|
167
|
+
globalPrefix: http.prefix,
|
|
168
|
+
versioning: http.versioning,
|
|
169
|
+
title: docs?.title ?? "Bazis UI profiles",
|
|
170
|
+
version: docs?.version ?? "1.0.0",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function declarationName(value: unknown): string {
|
|
175
|
+
if (typeof value === "function") {
|
|
176
|
+
return value.name || "<anonymous>";
|
|
177
|
+
}
|
|
178
|
+
if (value === null) {
|
|
179
|
+
return "null";
|
|
180
|
+
}
|
|
181
|
+
return typeof value;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** @internal Exported for hosting contract tests. */
|
|
185
|
+
export function normalizeUiSurfaceHostingOptions(
|
|
186
|
+
option: RunAppOptions["ui"],
|
|
187
|
+
http: HttpModuleOptions,
|
|
188
|
+
): UiSurfaceHostingOptions | undefined {
|
|
189
|
+
if (option === undefined) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
requirePublishedSurfaces(option.surfaces);
|
|
193
|
+
return {
|
|
194
|
+
app: {
|
|
195
|
+
name: option.app?.name ?? "Bazis",
|
|
196
|
+
version: option.app?.version ?? "1.0.0",
|
|
197
|
+
},
|
|
198
|
+
...uiSurfaceHostingPaths(http),
|
|
199
|
+
surfaces: option.surfaces,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function requirePublishedSurfaces(surfaces: readonly RunAppUiSurfaceOptions[]): void {
|
|
204
|
+
if (surfaces.length === 0) {
|
|
205
|
+
throw new TypeError("UI hosting requires at least one explicitly registered surface.");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function uiSurfaceHostingPaths(http: HttpModuleOptions): Pick<UiSurfaceHostingOptions, "apiBasePath"> {
|
|
210
|
+
const prefix = http.prefix?.trim() ?? "";
|
|
211
|
+
return {
|
|
212
|
+
apiBasePath: prefix.length === 0 ? "/" : normalizeAbsolutePath(prefix),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function normalizeAbsolutePath(path: string): string {
|
|
217
|
+
const trimmed = path.trim();
|
|
218
|
+
const prefixed = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
219
|
+
return `/${prefixed.split("/").filter((part) => part.length > 0).join("/")}`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The single application entry point, simpler than `NestFactory`.
|
|
224
|
+
*
|
|
225
|
+
* ```ts
|
|
226
|
+
* // main.ts
|
|
227
|
+
* import { runApp } from "@/core/app";
|
|
228
|
+
* import { AppModule } from "./modules/App.module";
|
|
229
|
+
*
|
|
230
|
+
* await runApp(AppModule, { http: { port: 3000, prefix: "api" } });
|
|
231
|
+
* ```
|
|
232
|
+
*
|
|
233
|
+
* It does three things you would otherwise write by hand:
|
|
234
|
+
* 1. starts the HTTP server and collects controllers from the whole module tree;
|
|
235
|
+
* 2. plugs in the request body validator (DIP glue between the kernel and the library);
|
|
236
|
+
* 3. starts the kernel with graceful shutdown on SIGINT/SIGTERM.
|
|
237
|
+
*
|
|
238
|
+
* The root module stays clean: `@Module({ imports: [UsersModule] })`.
|
|
239
|
+
*/
|
|
240
|
+
export async function runApp(root: BazisModuleRef, options: RunAppOptions = {}): Promise<number> {
|
|
241
|
+
const configure = options.configure;
|
|
242
|
+
await loadBazisGeneratedRuntime();
|
|
243
|
+
|
|
244
|
+
// Infrastructure and cache are global modules; add them to the graph next to the feature root.
|
|
245
|
+
const globals: BazisModuleRef[] = [];
|
|
246
|
+
if (options.infra !== undefined) {
|
|
247
|
+
globals.push(options.infra);
|
|
248
|
+
}
|
|
249
|
+
if (options.cache !== undefined) {
|
|
250
|
+
globals.push(options.cache);
|
|
251
|
+
}
|
|
252
|
+
const appRoot: BazisModuleRef =
|
|
253
|
+
globals.length > 0 || options.config !== undefined
|
|
254
|
+
? {
|
|
255
|
+
imports: [...globals, root],
|
|
256
|
+
...(options.config !== undefined ? { config: options.config } : {}),
|
|
257
|
+
}
|
|
258
|
+
: root;
|
|
259
|
+
|
|
260
|
+
if (options.http !== undefined) {
|
|
261
|
+
// Validation is glued in the composition root (the HTTP kernel only knows
|
|
262
|
+
// the `ModelValidator` port; the validation engine is a library).
|
|
263
|
+
const validator = options.validator ?? modelValidatorAdapter;
|
|
264
|
+
// Keep the legacy bridge for direct bindModel() callers, while also
|
|
265
|
+
// passing an instance-owned validator to the HTTP server. Capturing it per
|
|
266
|
+
// server prevents another app in the same process from changing validation
|
|
267
|
+
// behavior after startup.
|
|
268
|
+
useModelValidator(validator);
|
|
269
|
+
|
|
270
|
+
const httpAppRoot = withUiRuntime(
|
|
271
|
+
{ imports: [appRoot, ...(options.http.imports ?? [])] },
|
|
272
|
+
options.ui,
|
|
273
|
+
options.http,
|
|
274
|
+
);
|
|
275
|
+
const httpRoot = httpModule({
|
|
276
|
+
...options.http,
|
|
277
|
+
validator,
|
|
278
|
+
imports: [httpAppRoot],
|
|
279
|
+
});
|
|
280
|
+
const runtimeRoot = options.grpc === undefined ? httpRoot : {
|
|
281
|
+
imports: [httpRoot, grpcModule({ ...options.grpc, validator: options.grpc.validator === undefined ? validator : options.grpc.validator, imports: [appRoot, ...(options.grpc.imports ?? [])] })],
|
|
282
|
+
};
|
|
283
|
+
return Bazis.run(runtimeRoot, options.kernel, configure);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (options.validator) {
|
|
287
|
+
useModelValidator(options.validator);
|
|
288
|
+
}
|
|
289
|
+
const runtimeRoot = withUiRuntime(appRoot, options.ui, undefined);
|
|
290
|
+
const transportRoot = options.grpc === undefined ? runtimeRoot
|
|
291
|
+
: grpcModule({ ...options.grpc, validator: options.grpc.validator === undefined ? options.validator ?? modelValidatorAdapter : options.grpc.validator, imports: [runtimeRoot, ...(options.grpc.imports ?? [])] });
|
|
292
|
+
return Bazis.run(transportRoot, options.kernel, configure);
|
|
293
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export {
|
|
2
|
+
EN_UI_LABELS,
|
|
3
|
+
resolveUiProfileAuthoringV1,
|
|
4
|
+
RU_UI_LABELS,
|
|
5
|
+
type ResolveUiProfileAuthoringV1Options,
|
|
6
|
+
type UiLabels,
|
|
7
|
+
type ResolveUiProfileAuthoringV1Result,
|
|
8
|
+
} from "./uiProfileResolver";
|
|
9
|
+
export type {
|
|
10
|
+
RunAppUiAppInfo,
|
|
11
|
+
RunAppUiOptions,
|
|
12
|
+
RunAppUiSurfaceOptions,
|
|
13
|
+
} from "./uiSurfaceHosting";
|
|
14
|
+
export {
|
|
15
|
+
UI_SURFACE_SESSION_V1_API_VERSION,
|
|
16
|
+
UI_SURFACE_SESSION_V1_KIND,
|
|
17
|
+
UiSurfaceDocumentProvider,
|
|
18
|
+
} from "./uiSurfaceHttp";
|
|
19
|
+
export type {
|
|
20
|
+
UiSurfaceOperationRole,
|
|
21
|
+
UiSurfacePolicyDecision,
|
|
22
|
+
UiSurfacePolicyInput,
|
|
23
|
+
UiSurfacePolicyPageInput,
|
|
24
|
+
UiSurfacePolicyResourceInput,
|
|
25
|
+
UiSurfacePageDecision,
|
|
26
|
+
UiSurfaceResourceDecision,
|
|
27
|
+
UiSurfaceSessionUser,
|
|
28
|
+
UiSurfaceSessionV1,
|
|
29
|
+
} from "./uiSurfaceHttp";
|