effect 4.1.0 → 4.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/THIRD_PARTY_NOTICES.md +62 -0
- package/ai-docs/package.json +2 -2
- package/dist/BigDecimal.d.ts +139 -7
- package/dist/BigDecimal.d.ts.map +1 -1
- package/dist/BigDecimal.js +83 -14
- package/dist/BigDecimal.js.map +1 -1
- package/dist/ByteSize.d.ts.map +1 -1
- package/dist/ByteSize.js +27 -14
- package/dist/ByteSize.js.map +1 -1
- package/dist/Equal.d.ts +2 -2
- package/dist/Equal.d.ts.map +1 -1
- package/dist/Equal.js +3 -3
- package/dist/Equal.js.map +1 -1
- package/dist/Hash.d.ts +3 -2
- package/dist/Hash.d.ts.map +1 -1
- package/dist/Hash.js +5 -4
- package/dist/Hash.js.map +1 -1
- package/dist/Iterable.d.ts.map +1 -1
- package/dist/Iterable.js +38 -32
- package/dist/Iterable.js.map +1 -1
- package/dist/JsonSchema.d.ts.map +1 -1
- package/dist/JsonSchema.js +27 -6
- package/dist/JsonSchema.js.map +1 -1
- package/dist/MutableRef.d.ts.map +1 -1
- package/dist/MutableRef.js +0 -7
- package/dist/MutableRef.js.map +1 -1
- package/dist/Path.d.ts.map +1 -1
- package/dist/Path.js +5 -1
- package/dist/Path.js.map +1 -1
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +2 -1
- package/dist/Pool.js.map +1 -1
- package/dist/Ref.d.ts.map +1 -1
- package/dist/Ref.js +0 -8
- package/dist/Ref.js.map +1 -1
- package/dist/Schedule.d.ts.map +1 -1
- package/dist/Schedule.js +8 -3
- package/dist/Schedule.js.map +1 -1
- package/dist/Schema.d.ts +2 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +2 -1
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +4 -2
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +4 -2
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +2 -2
- package/dist/SchemaTransformation.js +2 -2
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +6 -5
- package/dist/Stream.js.map +1 -1
- package/dist/ai/McpClient.d.ts +171 -19
- package/dist/ai/McpClient.d.ts.map +1 -1
- package/dist/ai/McpClient.js +277 -66
- package/dist/ai/McpClient.js.map +1 -1
- package/dist/ai/McpSchema.d.ts +108 -0
- package/dist/ai/McpSchema.d.ts.map +1 -1
- package/dist/ai/McpSchema.js +99 -0
- package/dist/ai/McpSchema.js.map +1 -1
- package/dist/ai/McpServer.d.ts +120 -6
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +258 -49
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Prompt.d.ts.map +1 -1
- package/dist/ai/Prompt.js +20 -11
- package/dist/ai/Prompt.js.map +1 -1
- package/dist/ai/Tool.d.ts.map +1 -1
- package/dist/ai/Tool.js +5 -7
- package/dist/ai/Tool.js.map +1 -1
- package/dist/ai/internal/mcpCore.js +72 -3
- package/dist/ai/internal/mcpCore.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js +3 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js +44 -8
- package/dist/ai/internal/mcpProtocol/v2026_07_28.js.map +1 -1
- package/dist/ai/internal/mcpProtocol.js +12 -0
- package/dist/ai/internal/mcpProtocol.js.map +1 -1
- package/dist/ai/internal/mcpRuntime.js +3 -3
- package/dist/ai/internal/mcpRuntime.js.map +1 -1
- package/dist/ai/internal/mcpSkills.d.ts +2 -0
- package/dist/ai/internal/mcpSkills.d.ts.map +1 -0
- package/dist/ai/internal/mcpSkills.js +428 -0
- package/dist/ai/internal/mcpSkills.js.map +1 -0
- package/dist/ai/internal/structured-output.js +11 -2
- package/dist/ai/internal/structured-output.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +30 -11
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/Entity.d.ts +26 -0
- package/dist/cluster/Entity.d.ts.map +1 -1
- package/dist/cluster/Entity.js.map +1 -1
- package/dist/cluster/MessageStorage.d.ts +6 -6
- package/dist/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/cluster/MessageStorage.js +1 -3
- package/dist/cluster/MessageStorage.js.map +1 -1
- package/dist/cluster/Reply.d.ts +1 -1
- package/dist/cluster/Reply.d.ts.map +1 -1
- package/dist/cluster/Reply.js.map +1 -1
- package/dist/cluster/Runners.d.ts.map +1 -1
- package/dist/cluster/Runners.js +13 -2
- package/dist/cluster/Runners.js.map +1 -1
- package/dist/cluster/Sharding.d.ts +13 -0
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +4 -1
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/internal/clusterAbandon.d.ts.map +1 -1
- package/dist/cluster/internal/clusterAbandon.js +6 -4
- package/dist/cluster/internal/clusterAbandon.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +63 -11
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/cluster/internal/transactionNotifications.d.ts +5 -0
- package/dist/cluster/internal/transactionNotifications.d.ts.map +1 -0
- package/dist/cluster/internal/transactionNotifications.js +5 -0
- package/dist/cluster/internal/transactionNotifications.js.map +1 -0
- package/dist/crypto/Aead.d.ts +2 -1
- package/dist/crypto/Aead.d.ts.map +1 -1
- package/dist/crypto/Aead.js +2 -2
- package/dist/crypto/Aead.js.map +1 -1
- package/dist/crypto/Cipher.d.ts +2 -1
- package/dist/crypto/Cipher.d.ts.map +1 -1
- package/dist/crypto/Cipher.js +2 -2
- package/dist/crypto/Cipher.js.map +1 -1
- package/dist/crypto/KeyAgreement.d.ts +3 -2
- package/dist/crypto/KeyAgreement.d.ts.map +1 -1
- package/dist/crypto/KeyAgreement.js +2 -2
- package/dist/crypto/KeyAgreement.js.map +1 -1
- package/dist/crypto/KeyFormat.d.ts +33 -1
- package/dist/crypto/KeyFormat.d.ts.map +1 -1
- package/dist/crypto/KeyFormat.js.map +1 -1
- package/dist/crypto/KeyWrap.d.ts +4 -3
- package/dist/crypto/KeyWrap.d.ts.map +1 -1
- package/dist/crypto/KeyWrap.js +2 -2
- package/dist/crypto/KeyWrap.js.map +1 -1
- package/dist/crypto/Mac.d.ts +2 -1
- package/dist/crypto/Mac.d.ts.map +1 -1
- package/dist/crypto/Mac.js +2 -2
- package/dist/crypto/Mac.js.map +1 -1
- package/dist/crypto/Signature.d.ts +3 -2
- package/dist/crypto/Signature.d.ts.map +1 -1
- package/dist/crypto/Signature.js +2 -2
- package/dist/crypto/Signature.js.map +1 -1
- package/dist/crypto/WebCrypto.d.ts +19 -0
- package/dist/crypto/WebCrypto.d.ts.map +1 -1
- package/dist/crypto/WebCrypto.js.map +1 -1
- package/dist/crypto/internal/asymmetric.js.map +1 -1
- package/dist/crypto/internal/key.js +3 -2
- package/dist/crypto/internal/key.js.map +1 -1
- package/dist/encoding/Base64Url.d.ts.map +1 -1
- package/dist/encoding/Base64Url.js +26 -3
- package/dist/encoding/Base64Url.js.map +1 -1
- package/dist/encoding/Json5.d.ts +44 -0
- package/dist/encoding/Json5.d.ts.map +1 -0
- package/dist/encoding/Json5.js +56 -0
- package/dist/encoding/Json5.js.map +1 -0
- package/dist/encoding/Jsonc.d.ts +47 -0
- package/dist/encoding/Jsonc.d.ts.map +1 -0
- package/dist/encoding/Jsonc.js +120 -0
- package/dist/encoding/Jsonc.js.map +1 -0
- package/dist/encoding/Ndjson.d.ts +5 -4
- package/dist/encoding/Ndjson.d.ts.map +1 -1
- package/dist/encoding/Ndjson.js +6 -5
- package/dist/encoding/Ndjson.js.map +1 -1
- package/dist/encoding/SchemaBinary.d.ts +94 -0
- package/dist/encoding/SchemaBinary.d.ts.map +1 -1
- package/dist/encoding/SchemaBinary.js +219 -6
- package/dist/encoding/SchemaBinary.js.map +1 -1
- package/dist/encoding/Sse.d.ts +3 -1
- package/dist/encoding/Sse.d.ts.map +1 -1
- package/dist/encoding/Sse.js +5 -3
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/encoding/index.d.ts +10 -0
- package/dist/encoding/index.d.ts.map +1 -1
- package/dist/encoding/index.js +10 -0
- package/dist/encoding/index.js.map +1 -1
- package/dist/eventlog/EventLog.d.ts +7 -0
- package/dist/eventlog/EventLog.d.ts.map +1 -1
- package/dist/eventlog/EventLog.js +7 -0
- package/dist/eventlog/EventLog.js.map +1 -1
- package/dist/eventlog/EventLogServer.d.ts +7 -1
- package/dist/eventlog/EventLogServer.d.ts.map +1 -1
- package/dist/eventlog/EventLogServer.js +55 -24
- package/dist/eventlog/EventLogServer.js.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.d.ts +10 -0
- package/dist/eventlog/EventLogServerEncrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerEncrypted.js.map +1 -1
- package/dist/eventlog/EventLogServerUnencrypted.d.ts +17 -0
- package/dist/eventlog/EventLogServerUnencrypted.d.ts.map +1 -1
- package/dist/eventlog/EventLogServerUnencrypted.js +14 -2
- package/dist/eventlog/EventLogServerUnencrypted.js.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.d.ts +21 -0
- package/dist/eventlog/EventLogSessionAuth.d.ts.map +1 -1
- package/dist/eventlog/EventLogSessionAuth.js +22 -0
- package/dist/eventlog/EventLogSessionAuth.js.map +1 -1
- package/dist/graphql/GraphQLClient.d.ts +3 -1
- package/dist/graphql/GraphQLClient.d.ts.map +1 -1
- package/dist/graphql/GraphQLClient.js.map +1 -1
- package/dist/graphql/GraphQLClientError.d.ts +14 -9
- package/dist/graphql/GraphQLClientError.d.ts.map +1 -1
- package/dist/graphql/GraphQLClientError.js +14 -21
- package/dist/graphql/GraphQLClientError.js.map +1 -1
- package/dist/graphql/GraphQLProtocol.d.ts +12 -3
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -1
- package/dist/graphql/GraphQLProtocol.js +4 -1
- package/dist/graphql/GraphQLProtocol.js.map +1 -1
- package/dist/http/HttpClient.d.ts +204 -16
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +93 -13
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/http/HttpServerRequest.js +38 -22
- package/dist/http/HttpServerRequest.js.map +1 -1
- package/dist/http/internal/mimeTypes.d.ts +4 -1
- package/dist/http/internal/mimeTypes.d.ts.map +1 -1
- package/dist/http/internal/mimeTypes.js +4 -1
- package/dist/http/internal/mimeTypes.js.map +1 -1
- package/dist/http-api/HttpApiSchema.js +1 -1
- package/dist/http-api/HttpApiSchema.js.map +1 -1
- package/dist/internal/dateTime.js +66 -27
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +10 -0
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/glob.js +234 -56
- package/dist/internal/glob.js.map +1 -1
- package/dist/internal/graphql.js +21 -7
- package/dist/internal/graphql.js.map +1 -1
- package/dist/internal/graphqlHeaders.d.ts +7 -0
- package/dist/internal/graphqlHeaders.d.ts.map +1 -1
- package/dist/internal/graphqlHeaders.js +11 -0
- package/dist/internal/graphqlHeaders.js.map +1 -1
- package/dist/internal/jsonParser.d.ts +5 -0
- package/dist/internal/jsonParser.d.ts.map +1 -0
- package/dist/internal/jsonParser.js +280 -0
- package/dist/internal/jsonParser.js.map +1 -0
- package/dist/internal/persistence.js +8 -1
- package/dist/internal/persistence.js.map +1 -1
- package/dist/internal/request.js +29 -42
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +7 -8
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/sql.js +16 -0
- package/dist/internal/sql.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/jose/JoseError.d.ts +285 -0
- package/dist/jose/JoseError.d.ts.map +1 -0
- package/dist/jose/JoseError.js +269 -0
- package/dist/jose/JoseError.js.map +1 -0
- package/dist/jose/Jwe.d.ts +128 -0
- package/dist/jose/Jwe.d.ts.map +1 -0
- package/dist/jose/Jwe.js +134 -0
- package/dist/jose/Jwe.js.map +1 -0
- package/dist/jose/Jwk.d.ts +597 -0
- package/dist/jose/Jwk.d.ts.map +1 -0
- package/dist/jose/Jwk.js +503 -0
- package/dist/jose/Jwk.js.map +1 -0
- package/dist/jose/Jwks.d.ts +236 -0
- package/dist/jose/Jwks.d.ts.map +1 -0
- package/dist/jose/Jwks.js +306 -0
- package/dist/jose/Jwks.js.map +1 -0
- package/dist/jose/Jws.d.ts +177 -0
- package/dist/jose/Jws.d.ts.map +1 -0
- package/dist/jose/Jws.js +183 -0
- package/dist/jose/Jws.js.map +1 -0
- package/dist/jose/Jwt.d.ts +270 -0
- package/dist/jose/Jwt.d.ts.map +1 -0
- package/dist/jose/Jwt.js +293 -0
- package/dist/jose/Jwt.js.map +1 -0
- package/dist/jose/index.d.ts +51 -0
- package/dist/jose/index.d.ts.map +1 -0
- package/dist/jose/index.js +52 -0
- package/dist/jose/index.js.map +1 -0
- package/dist/jose/internal/compact.d.ts +2 -0
- package/dist/jose/internal/compact.d.ts.map +1 -0
- package/dist/jose/internal/compact.js +179 -0
- package/dist/jose/internal/compact.js.map +1 -0
- package/dist/net/Host.d.ts.map +1 -1
- package/dist/net/Host.js +5 -10
- package/dist/net/Host.js.map +1 -1
- package/dist/observability/OtlpExporter.d.ts +4 -0
- package/dist/observability/OtlpExporter.d.ts.map +1 -1
- package/dist/observability/OtlpExporter.js +40 -12
- package/dist/observability/OtlpExporter.js.map +1 -1
- package/dist/observability/OtlpSerialization.d.ts +1 -1
- package/dist/observability/OtlpSerialization.d.ts.map +1 -1
- package/dist/observability/OtlpSerialization.js +10 -4
- package/dist/observability/OtlpSerialization.js.map +1 -1
- package/dist/observability/internal/otlpProtobuf.js +3 -3
- package/dist/observability/internal/otlpProtobuf.js.map +1 -1
- package/dist/observability/internal/protobuf.js +6 -0
- package/dist/observability/internal/protobuf.js.map +1 -1
- package/dist/persistence/CircuitBreaker.d.ts +98 -38
- package/dist/persistence/CircuitBreaker.d.ts.map +1 -1
- package/dist/persistence/CircuitBreaker.js +67 -29
- package/dist/persistence/CircuitBreaker.js.map +1 -1
- package/dist/persistence/RateLimiter.d.ts +15 -0
- package/dist/persistence/RateLimiter.d.ts.map +1 -1
- package/dist/persistence/RateLimiter.js +76 -16
- package/dist/persistence/RateLimiter.js.map +1 -1
- package/dist/persistence/index.d.ts +1 -1
- package/dist/persistence/index.js +1 -1
- package/dist/reactivity/AtomRegistry.js +17 -7
- package/dist/reactivity/AtomRegistry.js.map +1 -1
- package/dist/rpc/Rpc.d.ts +1 -1
- package/dist/rpc/Rpc.d.ts.map +1 -1
- package/dist/rpc/Rpc.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts +14 -2
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +38 -21
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcMessage.d.ts +3 -2
- package/dist/rpc/RpcMessage.d.ts.map +1 -1
- package/dist/rpc/RpcMessage.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +10 -1
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/sql/Migrator.d.ts +9 -1
- package/dist/sql/Migrator.d.ts.map +1 -1
- package/dist/sql/Migrator.js +18 -6
- package/dist/sql/Migrator.js.map +1 -1
- package/dist/sql/SqlClient.d.ts +46 -3
- package/dist/sql/SqlClient.d.ts.map +1 -1
- package/dist/sql/SqlClient.js +40 -15
- package/dist/sql/SqlClient.js.map +1 -1
- package/dist/sql/Statement.d.ts +46 -3
- package/dist/sql/Statement.d.ts.map +1 -1
- package/dist/sql/Statement.js +32 -26
- package/dist/sql/Statement.js.map +1 -1
- package/dist/workflow/Workflow.d.ts +4 -0
- package/dist/workflow/Workflow.d.ts.map +1 -1
- package/dist/workflow/Workflow.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +5 -0
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +7 -3
- package/src/BigDecimal.ts +170 -16
- package/src/ByteSize.ts +29 -14
- package/src/Equal.ts +3 -3
- package/src/Hash.ts +5 -4
- package/src/Iterable.ts +28 -19
- package/src/JsonSchema.ts +45 -7
- package/src/MutableRef.ts +1 -8
- package/src/Path.ts +6 -1
- package/src/Pool.ts +2 -1
- package/src/Ref.ts +0 -8
- package/src/Schedule.ts +8 -6
- package/src/Schema.ts +3 -2
- package/src/SchemaRepresentation.ts +4 -2
- package/src/SchemaTransformation.ts +2 -2
- package/src/Stream.ts +6 -5
- package/src/ai/McpClient.ts +488 -91
- package/src/ai/McpSchema.ts +119 -0
- package/src/ai/McpServer.ts +302 -56
- package/src/ai/Prompt.ts +16 -11
- package/src/ai/Tool.ts +5 -10
- package/src/ai/internal/mcpCore.ts +165 -12
- package/src/ai/internal/mcpProtocol/v2024_11_05.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_03_26.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_06_18.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2025_11_25.ts +3 -1
- package/src/ai/internal/mcpProtocol/v2026_07_28.ts +42 -9
- package/src/ai/internal/mcpProtocol.ts +15 -0
- package/src/ai/internal/mcpRuntime.ts +6 -3
- package/src/ai/internal/mcpSkills.ts +480 -0
- package/src/ai/internal/structured-output.ts +10 -4
- package/src/cluster/ClusterWorkflowEngine.ts +48 -33
- package/src/cluster/Entity.ts +52 -0
- package/src/cluster/MessageStorage.ts +3 -6
- package/src/cluster/Reply.ts +1 -1
- package/src/cluster/Runners.ts +16 -2
- package/src/cluster/Sharding.ts +17 -1
- package/src/cluster/internal/clusterAbandon.ts +7 -7
- package/src/cluster/internal/entityManager.ts +89 -15
- package/src/cluster/internal/transactionNotifications.ts +7 -0
- package/src/crypto/Aead.ts +3 -3
- package/src/crypto/Cipher.ts +3 -3
- package/src/crypto/KeyAgreement.ts +4 -4
- package/src/crypto/KeyFormat.ts +30 -1
- package/src/crypto/KeyWrap.ts +6 -6
- package/src/crypto/Mac.ts +3 -3
- package/src/crypto/Signature.ts +4 -4
- package/src/crypto/WebCrypto.ts +20 -0
- package/src/crypto/internal/asymmetric.ts +2 -1
- package/src/crypto/internal/key.ts +12 -5
- package/src/encoding/Base64Url.ts +27 -3
- package/src/encoding/Json5.ts +59 -0
- package/src/encoding/Jsonc.ts +126 -0
- package/src/encoding/Ndjson.ts +6 -5
- package/src/encoding/SchemaBinary.ts +228 -7
- package/src/encoding/Sse.ts +5 -3
- package/src/encoding/index.ts +12 -0
- package/src/eventlog/EventLog.ts +7 -0
- package/src/eventlog/EventLogServer.ts +67 -24
- package/src/eventlog/EventLogServerEncrypted.ts +5 -0
- package/src/eventlog/EventLogServerUnencrypted.ts +19 -2
- package/src/eventlog/EventLogSessionAuth.ts +26 -0
- package/src/graphql/GraphQLClient.ts +3 -1
- package/src/graphql/GraphQLClientError.ts +15 -22
- package/src/graphql/GraphQLProtocol.ts +12 -3
- package/src/http/HttpClient.ts +244 -33
- package/src/http/HttpServerRequest.ts +61 -23
- package/src/http/internal/mimeTypes.ts +4 -1
- package/src/http-api/HttpApiSchema.ts +1 -1
- package/src/internal/dateTime.ts +80 -27
- package/src/internal/effect.ts +6 -0
- package/src/internal/glob.ts +279 -63
- package/src/internal/graphql.ts +27 -9
- package/src/internal/graphqlHeaders.ts +13 -0
- package/src/internal/jsonParser.ts +307 -0
- package/src/internal/persistence.ts +9 -1
- package/src/internal/request.ts +51 -58
- package/src/internal/schema/fromJsonSchemaDocument.ts +11 -10
- package/src/internal/sql.ts +25 -0
- package/src/internal/version.ts +1 -1
- package/src/jose/JoseError.ts +329 -0
- package/src/jose/Jwe.ts +196 -0
- package/src/jose/Jwk.ts +777 -0
- package/src/jose/Jwks.ts +418 -0
- package/src/jose/Jws.ts +312 -0
- package/src/jose/Jwt.ts +493 -0
- package/src/jose/index.ts +58 -0
- package/src/jose/internal/compact.ts +195 -0
- package/src/net/Host.ts +5 -10
- package/src/observability/OtlpExporter.ts +42 -18
- package/src/observability/OtlpSerialization.ts +13 -5
- package/src/observability/internal/otlpProtobuf.ts +6 -6
- package/src/observability/internal/protobuf.ts +10 -0
- package/src/persistence/CircuitBreaker.ts +113 -48
- package/src/persistence/RateLimiter.ts +97 -19
- package/src/persistence/index.ts +1 -1
- package/src/reactivity/AtomRegistry.ts +19 -8
- package/src/rpc/Rpc.ts +3 -1
- package/src/rpc/RpcClient.ts +44 -24
- package/src/rpc/RpcMessage.ts +3 -2
- package/src/rpc/RpcServer.ts +12 -1
- package/src/sql/Migrator.ts +35 -18
- package/src/sql/SqlClient.ts +91 -22
- package/src/sql/Statement.ts +60 -35
- package/src/workflow/Workflow.ts +4 -0
- package/src/workflow/WorkflowEngine.ts +5 -0
package/src/jose/Jwk.ts
ADDED
|
@@ -0,0 +1,777 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Web Keys and the algorithm-bound keys the other `effect/jose` modules
|
|
3
|
+
* use.
|
|
4
|
+
*
|
|
5
|
+
* A key is imported for one algorithm and keeps it: a JWS or JWE operation
|
|
6
|
+
* takes its algorithm from the key, so a token cannot pick another one. The
|
|
7
|
+
* imported key wraps an `effect/crypto` key object, which redacts itself when
|
|
8
|
+
* printed and caches its native key.
|
|
9
|
+
*
|
|
10
|
+
* Importing honours the JWK's `alg`, `use`, and `key_ops` members, and
|
|
11
|
+
* rejects RSA keys shorter than 2048 bits.
|
|
12
|
+
*
|
|
13
|
+
* @stability unstable
|
|
14
|
+
* @since 4.1.1
|
|
15
|
+
*/
|
|
16
|
+
import * as Aead from "../crypto/Aead.ts"
|
|
17
|
+
import * as Digest from "../crypto/Digest.ts"
|
|
18
|
+
import * as KeyFormat from "../crypto/KeyFormat.ts"
|
|
19
|
+
import * as Mac from "../crypto/Mac.ts"
|
|
20
|
+
import * as SecureRandom from "../crypto/SecureRandom.ts"
|
|
21
|
+
import * as Signature from "../crypto/Signature.ts"
|
|
22
|
+
import * as Effect from "../Effect.ts"
|
|
23
|
+
import * as Base64Url from "../encoding/Base64Url.ts"
|
|
24
|
+
import * as Redacted from "../Redacted.ts"
|
|
25
|
+
import * as Schema from "../Schema.ts"
|
|
26
|
+
import {
|
|
27
|
+
cryptoFailure,
|
|
28
|
+
decodeSegment,
|
|
29
|
+
hasPrivateMembers,
|
|
30
|
+
invalidArgument,
|
|
31
|
+
invalidKey,
|
|
32
|
+
isCanonicalSegment,
|
|
33
|
+
noPrivateMembers,
|
|
34
|
+
publicKeyFailure,
|
|
35
|
+
utf8
|
|
36
|
+
} from "./internal/compact.ts"
|
|
37
|
+
import type { JoseError } from "./JoseError.ts"
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Schema for RSA, RSA-PSS, and ECDSA signatures with SHA-256, SHA-384, or
|
|
41
|
+
* SHA-512, and EdDSA signatures with Ed25519.
|
|
42
|
+
*
|
|
43
|
+
* @stability unstable
|
|
44
|
+
* @category schemas
|
|
45
|
+
* @since 4.1.1
|
|
46
|
+
*/
|
|
47
|
+
export const AsymmetricAlgorithm = Schema.Literals([
|
|
48
|
+
"RS256",
|
|
49
|
+
"RS384",
|
|
50
|
+
"RS512",
|
|
51
|
+
"PS256",
|
|
52
|
+
"PS384",
|
|
53
|
+
"PS512",
|
|
54
|
+
"ES256",
|
|
55
|
+
"ES384",
|
|
56
|
+
"ES512",
|
|
57
|
+
"EdDSA"
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* An asymmetric signature algorithm.
|
|
62
|
+
*
|
|
63
|
+
* @stability unstable
|
|
64
|
+
* @category models
|
|
65
|
+
* @since 4.1.1
|
|
66
|
+
*/
|
|
67
|
+
export type AsymmetricAlgorithm = typeof AsymmetricAlgorithm.Type
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Schema for the JWS algorithms: HS256, HS384, HS512, and the asymmetric
|
|
71
|
+
* algorithms.
|
|
72
|
+
*
|
|
73
|
+
* @stability unstable
|
|
74
|
+
* @category schemas
|
|
75
|
+
* @since 4.1.1
|
|
76
|
+
*/
|
|
77
|
+
export const Algorithm = Schema.Literals([
|
|
78
|
+
"HS256",
|
|
79
|
+
"HS384",
|
|
80
|
+
"HS512",
|
|
81
|
+
"RS256",
|
|
82
|
+
"RS384",
|
|
83
|
+
"RS512",
|
|
84
|
+
"PS256",
|
|
85
|
+
"PS384",
|
|
86
|
+
"PS512",
|
|
87
|
+
"ES256",
|
|
88
|
+
"ES384",
|
|
89
|
+
"ES512",
|
|
90
|
+
"EdDSA"
|
|
91
|
+
])
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* A JWS algorithm.
|
|
95
|
+
*
|
|
96
|
+
* @stability unstable
|
|
97
|
+
* @category models
|
|
98
|
+
* @since 4.1.1
|
|
99
|
+
*/
|
|
100
|
+
export type Algorithm = typeof Algorithm.Type
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* An HMAC signature algorithm using SHA-256, SHA-384, or SHA-512.
|
|
104
|
+
*
|
|
105
|
+
* @stability unstable
|
|
106
|
+
* @category models
|
|
107
|
+
* @since 4.1.1
|
|
108
|
+
*/
|
|
109
|
+
export type HmacAlgorithm = "HS256" | "HS384" | "HS512"
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The algorithms of a symmetric key: HMAC signatures, or direct A256GCM
|
|
113
|
+
* encryption.
|
|
114
|
+
*
|
|
115
|
+
* @stability unstable
|
|
116
|
+
* @category models
|
|
117
|
+
* @since 4.1.1
|
|
118
|
+
*/
|
|
119
|
+
export type SecretAlgorithm = HmacAlgorithm | "dir"
|
|
120
|
+
|
|
121
|
+
const metadata = {
|
|
122
|
+
kid: Schema.optionalKey(Schema.String),
|
|
123
|
+
alg: Schema.optionalKey(Schema.String),
|
|
124
|
+
use: Schema.optionalKey(Schema.String),
|
|
125
|
+
key_ops: Schema.optionalKey(Schema.Array(Schema.String))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const base64url = Schema.String.check(Schema.makeFilter(isCanonicalSegment, {
|
|
129
|
+
expected: "a canonical base64url encoded string"
|
|
130
|
+
}))
|
|
131
|
+
|
|
132
|
+
const rsa = { ...metadata, kty: Schema.Literal("RSA"), n: base64url, e: base64url }
|
|
133
|
+
const ec = {
|
|
134
|
+
...metadata,
|
|
135
|
+
kty: Schema.Literal("EC"),
|
|
136
|
+
crv: Schema.Literals(["P-256", "P-384", "P-521"]),
|
|
137
|
+
x: base64url,
|
|
138
|
+
y: base64url
|
|
139
|
+
}
|
|
140
|
+
const okp = { ...metadata, kty: Schema.Literal("OKP"), crv: Schema.Literal("Ed25519"), x: base64url }
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Schema for an RSA, P-256, P-384, P-521, or Ed25519 public JWK. Private and symmetric
|
|
144
|
+
* members, including RSA factors, are rejected.
|
|
145
|
+
*
|
|
146
|
+
* @stability unstable
|
|
147
|
+
* @category schemas
|
|
148
|
+
* @since 4.1.1
|
|
149
|
+
*/
|
|
150
|
+
export const PublicJwk = Schema.Union([
|
|
151
|
+
Schema.Struct({ ...rsa, ...noPrivateMembers }),
|
|
152
|
+
Schema.Struct({ ...ec, ...noPrivateMembers }),
|
|
153
|
+
Schema.Struct({ ...okp, ...noPrivateMembers })
|
|
154
|
+
])
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* An RSA, P-256, P-384, P-521, or Ed25519 public JWK.
|
|
158
|
+
*
|
|
159
|
+
* @stability unstable
|
|
160
|
+
* @category models
|
|
161
|
+
* @since 4.1.1
|
|
162
|
+
*/
|
|
163
|
+
export type PublicJwk = typeof PublicJwk.Type
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Schema for an RSA, P-256, P-384, P-521, or Ed25519 private JWK. RSA keys need their CRT
|
|
167
|
+
* members and cannot have more than two primes.
|
|
168
|
+
*
|
|
169
|
+
* @stability unstable
|
|
170
|
+
* @category schemas
|
|
171
|
+
* @since 4.1.1
|
|
172
|
+
*/
|
|
173
|
+
export const PrivateJwk = Schema.Union([
|
|
174
|
+
Schema.Struct({
|
|
175
|
+
...rsa,
|
|
176
|
+
d: base64url,
|
|
177
|
+
p: base64url,
|
|
178
|
+
q: base64url,
|
|
179
|
+
dp: base64url,
|
|
180
|
+
dq: base64url,
|
|
181
|
+
qi: base64url,
|
|
182
|
+
oth: Schema.optionalKey(Schema.Never)
|
|
183
|
+
}),
|
|
184
|
+
Schema.Struct({ ...ec, d: base64url }),
|
|
185
|
+
Schema.Struct({ ...okp, d: base64url })
|
|
186
|
+
])
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* An RSA, P-256, P-384, P-521, or Ed25519 private JWK.
|
|
190
|
+
*
|
|
191
|
+
* @stability unstable
|
|
192
|
+
* @category models
|
|
193
|
+
* @since 4.1.1
|
|
194
|
+
*/
|
|
195
|
+
export type PrivateJwk = typeof PrivateJwk.Type
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Schema for an octet-sequence JWK.
|
|
199
|
+
*
|
|
200
|
+
* @stability unstable
|
|
201
|
+
* @category schemas
|
|
202
|
+
* @since 4.1.1
|
|
203
|
+
*/
|
|
204
|
+
export const SecretJwk = Schema.Struct({ ...metadata, kty: Schema.Literal("oct"), k: Schema.String })
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* An octet-sequence JWK.
|
|
208
|
+
*
|
|
209
|
+
* @stability unstable
|
|
210
|
+
* @category models
|
|
211
|
+
* @since 4.1.1
|
|
212
|
+
*/
|
|
213
|
+
export type SecretJwk = typeof SecretJwk.Type
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* A public key bound to one asymmetric algorithm, with the JWK it was imported
|
|
217
|
+
* from.
|
|
218
|
+
*
|
|
219
|
+
* @stability unstable
|
|
220
|
+
* @category models
|
|
221
|
+
* @since 4.1.1
|
|
222
|
+
*/
|
|
223
|
+
export interface PublicKey {
|
|
224
|
+
readonly _tag: "PublicKey"
|
|
225
|
+
readonly algorithm: AsymmetricAlgorithm
|
|
226
|
+
readonly kid: string | undefined
|
|
227
|
+
readonly jwk: PublicJwk
|
|
228
|
+
readonly key: Signature.PublicKey
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* A private key bound to one asymmetric algorithm.
|
|
233
|
+
*
|
|
234
|
+
* @stability unstable
|
|
235
|
+
* @category models
|
|
236
|
+
* @since 4.1.1
|
|
237
|
+
*/
|
|
238
|
+
export interface PrivateKey {
|
|
239
|
+
readonly _tag: "PrivateKey"
|
|
240
|
+
readonly algorithm: AsymmetricAlgorithm
|
|
241
|
+
readonly kid: string | undefined
|
|
242
|
+
readonly key: Signature.PrivateKey
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* A symmetric key bound to an HMAC signature algorithm or to direct A256GCM encryption.
|
|
247
|
+
*
|
|
248
|
+
* @stability unstable
|
|
249
|
+
* @category models
|
|
250
|
+
* @since 4.1.1
|
|
251
|
+
*/
|
|
252
|
+
export interface SecretKey<A extends SecretAlgorithm = SecretAlgorithm> {
|
|
253
|
+
readonly _tag: "SecretKey"
|
|
254
|
+
readonly algorithm: A
|
|
255
|
+
readonly kid: string | undefined
|
|
256
|
+
readonly key: A extends HmacAlgorithm ? Mac.Key : Aead.Key
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* A key that signs JWS and JWT tokens.
|
|
261
|
+
*
|
|
262
|
+
* @stability unstable
|
|
263
|
+
* @category models
|
|
264
|
+
* @since 4.1.1
|
|
265
|
+
*/
|
|
266
|
+
export type SigningKey = PrivateKey | SecretKey<HmacAlgorithm>
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* A key that verifies JWS and JWT tokens.
|
|
270
|
+
*
|
|
271
|
+
* @stability unstable
|
|
272
|
+
* @category models
|
|
273
|
+
* @since 4.1.1
|
|
274
|
+
*/
|
|
275
|
+
export type VerificationKey = PublicKey | SecretKey<HmacAlgorithm>
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* A generated public JWK and its private JWK, both carrying `alg`, `use: "sig"`,
|
|
279
|
+
* and the requested `kid`.
|
|
280
|
+
*
|
|
281
|
+
* @stability unstable
|
|
282
|
+
* @category models
|
|
283
|
+
* @since 4.1.1
|
|
284
|
+
*/
|
|
285
|
+
export interface KeyPair {
|
|
286
|
+
readonly publicKey: PublicJwk
|
|
287
|
+
readonly privateKey: Redacted.Redacted<PrivateJwk>
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Options for {@link generateKeyPair}.
|
|
292
|
+
*
|
|
293
|
+
* @stability unstable
|
|
294
|
+
* @category models
|
|
295
|
+
* @since 4.1.1
|
|
296
|
+
*/
|
|
297
|
+
export interface GenerateKeyPairOptions {
|
|
298
|
+
readonly algorithm: AsymmetricAlgorithm
|
|
299
|
+
readonly kid?: string | undefined
|
|
300
|
+
/**
|
|
301
|
+
* RSA modulus length in bits. Defaults to 2048 and must be at least 2048.
|
|
302
|
+
*/
|
|
303
|
+
readonly modulusLength?: number | undefined
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const signatureAlgorithm = (algorithm: AsymmetricAlgorithm, modulusLength = 2048): Signature.Algorithm => {
|
|
307
|
+
switch (algorithm) {
|
|
308
|
+
case "RS256":
|
|
309
|
+
return Signature.rsaPkcs1v15({ hash: Digest.sha256, modulusLength })
|
|
310
|
+
case "RS384":
|
|
311
|
+
return Signature.rsaPkcs1v15({ hash: Digest.sha384, modulusLength })
|
|
312
|
+
case "RS512":
|
|
313
|
+
return Signature.rsaPkcs1v15({ hash: Digest.sha512, modulusLength })
|
|
314
|
+
case "PS256":
|
|
315
|
+
return Signature.rsaPss({ hash: Digest.sha256, modulusLength })
|
|
316
|
+
case "PS384":
|
|
317
|
+
return Signature.rsaPss({ hash: Digest.sha384, modulusLength })
|
|
318
|
+
case "PS512":
|
|
319
|
+
return Signature.rsaPss({ hash: Digest.sha512, modulusLength })
|
|
320
|
+
case "ES256":
|
|
321
|
+
return Signature.ecdsaP256
|
|
322
|
+
case "ES384":
|
|
323
|
+
return Signature.ecdsaP384
|
|
324
|
+
case "ES512":
|
|
325
|
+
return Signature.ecdsaP521
|
|
326
|
+
case "EdDSA":
|
|
327
|
+
return Signature.ed25519
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const hmacAlgorithms: Record<HmacAlgorithm, Mac.Algorithm> = {
|
|
332
|
+
HS256: Mac.hmacSha256,
|
|
333
|
+
HS384: Mac.hmacSha384,
|
|
334
|
+
HS512: Mac.hmacSha512
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const secretKeyLength = (algorithm: SecretAlgorithm): number =>
|
|
338
|
+
algorithm === "dir" ? 32 : hmacAlgorithms[algorithm].hash.outputLength
|
|
339
|
+
|
|
340
|
+
interface Metadata {
|
|
341
|
+
readonly alg?: string | undefined
|
|
342
|
+
readonly use?: string | undefined
|
|
343
|
+
readonly key_ops?: ReadonlyArray<string> | undefined
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// `key_ops` must allow every operation in `operations`; symmetric keys perform both.
|
|
347
|
+
const checkMetadata = (
|
|
348
|
+
jwk: Metadata,
|
|
349
|
+
algorithm: string,
|
|
350
|
+
use: "sig" | "enc",
|
|
351
|
+
operations: ReadonlyArray<string>
|
|
352
|
+
): Effect.Effect<void, JoseError> => {
|
|
353
|
+
if (jwk.alg !== undefined && jwk.alg !== algorithm) {
|
|
354
|
+
return invalidKey(`The JWK is for ${jwk.alg}, not ${algorithm}`)
|
|
355
|
+
}
|
|
356
|
+
if (jwk.use !== undefined && jwk.use !== use) {
|
|
357
|
+
return invalidKey(`The JWK use is ${jwk.use}, not ${use}`)
|
|
358
|
+
}
|
|
359
|
+
if (jwk.key_ops !== undefined && !operations.every((operation) => jwk.key_ops!.includes(operation))) {
|
|
360
|
+
return invalidKey(`The JWK key_ops must allow ${operations.join(" and ")}`)
|
|
361
|
+
}
|
|
362
|
+
return Effect.void
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Checked on the imported key, whose algorithm carries the actual modulus.
|
|
366
|
+
const checkModulus = (key: Signature.PublicKey | Signature.PrivateKey): Effect.Effect<void, JoseError> =>
|
|
367
|
+
(key.algorithm._tag === "RsaPss" || key.algorithm._tag === "RsaPkcs1v15") && key.algorithm.modulusLength < 2048
|
|
368
|
+
? invalidKey("RSA keys must have at least 2048 bits")
|
|
369
|
+
: Effect.void
|
|
370
|
+
|
|
371
|
+
// KeyFormat handles only key members; JOSE metadata is handled here.
|
|
372
|
+
const jsonWebKey = (jwk: object): KeyFormat.JsonWebKey => jwk
|
|
373
|
+
|
|
374
|
+
const isPublicJwk = Schema.is(PublicJwk)
|
|
375
|
+
const isPrivateJwk = Schema.is(PrivateJwk)
|
|
376
|
+
|
|
377
|
+
const exportJwk = (
|
|
378
|
+
key: Signature.PrivateKey | Signature.PublicKey,
|
|
379
|
+
algorithm: AsymmetricAlgorithm,
|
|
380
|
+
kid: string | undefined
|
|
381
|
+
): Effect.Effect<object, JoseError> =>
|
|
382
|
+
KeyFormat.encode(KeyFormat.jwk, key as KeyFormat.Key).pipe(
|
|
383
|
+
Effect.mapBoth({
|
|
384
|
+
onFailure: cryptoFailure("Could not export the key"),
|
|
385
|
+
onSuccess: (jwk) => ({ ...jwk, ...(kid === undefined ? {} : { kid }), alg: algorithm, use: "sig" })
|
|
386
|
+
})
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Generates a key pair for an asymmetric algorithm and returns it as JWKs.
|
|
391
|
+
*
|
|
392
|
+
* @see {@link importPrivate} for preparing the private JWK for signing
|
|
393
|
+
* @see {@link importPublic} for preparing the public JWK for verification
|
|
394
|
+
*
|
|
395
|
+
* @stability unstable
|
|
396
|
+
* @category constructors
|
|
397
|
+
* @since 4.1.1
|
|
398
|
+
*/
|
|
399
|
+
export const generateKeyPair = Effect.fnUntraced(function*(
|
|
400
|
+
options: GenerateKeyPairOptions
|
|
401
|
+
): Effect.fn.Return<KeyPair, JoseError, Signature.Signature> {
|
|
402
|
+
const { algorithm, kid, modulusLength } = options
|
|
403
|
+
if (modulusLength !== undefined && (!Number.isSafeInteger(modulusLength) || modulusLength < 2048)) {
|
|
404
|
+
return yield* invalidArgument("modulusLength must be an integer of at least 2048")
|
|
405
|
+
}
|
|
406
|
+
const signature = yield* Signature.Signature
|
|
407
|
+
const pair = yield* signature.generateKeyPair(signatureAlgorithm(algorithm, modulusLength)).pipe(
|
|
408
|
+
Effect.mapError(cryptoFailure(`Could not generate a ${algorithm} key pair`))
|
|
409
|
+
)
|
|
410
|
+
const publicJwk = yield* exportJwk(pair.publicKey, algorithm, kid)
|
|
411
|
+
const privateJwk = yield* exportJwk(pair.privateKey, algorithm, kid)
|
|
412
|
+
return { publicKey: publicJwk as PublicJwk, privateKey: Redacted.make(privateJwk as PrivateJwk) }
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Generates a redacted secret JWK carrying its `alg`, `use`, and optional `kid`.
|
|
417
|
+
*
|
|
418
|
+
* **Details**
|
|
419
|
+
*
|
|
420
|
+
* HMAC keys contain 32, 48, or 64 random bytes for HS256, HS384, or HS512.
|
|
421
|
+
* Direct A256GCM keys contain 32 bytes and use `enc` instead of `sig`.
|
|
422
|
+
*
|
|
423
|
+
* @see {@link importSecret} for preparing the JWK for use
|
|
424
|
+
* @see {@link generateKeyPair} for asymmetric keys
|
|
425
|
+
*
|
|
426
|
+
* @stability unstable
|
|
427
|
+
* @category constructors
|
|
428
|
+
* @since 4.1.1
|
|
429
|
+
*/
|
|
430
|
+
export const generateSecret = (
|
|
431
|
+
algorithm: SecretAlgorithm,
|
|
432
|
+
options?: { readonly kid?: string | undefined }
|
|
433
|
+
): Effect.Effect<Redacted.Redacted<SecretJwk>, never, SecureRandom.SecureRandom> =>
|
|
434
|
+
Effect.map(
|
|
435
|
+
SecureRandom.SecureRandom.use((random) => random.randomBytes(secretKeyLength(algorithm))),
|
|
436
|
+
(bytes) =>
|
|
437
|
+
Redacted.make({
|
|
438
|
+
kty: "oct",
|
|
439
|
+
k: Base64Url.encode(bytes),
|
|
440
|
+
alg: algorithm,
|
|
441
|
+
use: algorithm === "dir" ? "enc" : "sig",
|
|
442
|
+
...(options?.kid === undefined ? {} : { kid: options.kid })
|
|
443
|
+
})
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Imports a public JWK for an asymmetric algorithm.
|
|
448
|
+
*
|
|
449
|
+
* **Details**
|
|
450
|
+
*
|
|
451
|
+
* The key's family and curve must fit the algorithm, and any `alg`, `use`, or
|
|
452
|
+
* `key_ops` member must allow verification with it. Private members are
|
|
453
|
+
* rejected. To import untrusted JSON, decode it with {@link PublicJwk} first.
|
|
454
|
+
*
|
|
455
|
+
* @see {@link importPrivate}
|
|
456
|
+
* @see {@link exportPublic}
|
|
457
|
+
*
|
|
458
|
+
* @stability unstable
|
|
459
|
+
* @category constructors
|
|
460
|
+
* @since 4.1.1
|
|
461
|
+
*/
|
|
462
|
+
export const importPublic = Effect.fnUntraced(function*(
|
|
463
|
+
jwk: PublicJwk,
|
|
464
|
+
algorithm: AsymmetricAlgorithm
|
|
465
|
+
): Effect.fn.Return<PublicKey, JoseError> {
|
|
466
|
+
if (hasPrivateMembers(jwk)) return yield* invalidKey("A public JWK cannot contain private members")
|
|
467
|
+
yield* checkMetadata(jwk, algorithm, "sig", ["verify"])
|
|
468
|
+
if (!isPublicJwk(jwk)) return yield* invalidKey("Expected a public JWK with base64url key members")
|
|
469
|
+
const key = yield* KeyFormat.decodePublic(KeyFormat.jwk, signatureAlgorithm(algorithm), jsonWebKey(jwk)).pipe(
|
|
470
|
+
Effect.mapError(publicKeyFailure)
|
|
471
|
+
)
|
|
472
|
+
yield* checkModulus(key)
|
|
473
|
+
return { _tag: "PublicKey", algorithm, kid: jwk.kid, jwk, key }
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Imports a private JWK for an asymmetric algorithm.
|
|
478
|
+
*
|
|
479
|
+
* @see {@link importPkcs8} for importing DER or PEM keys
|
|
480
|
+
* @see {@link exportPrivate}
|
|
481
|
+
*
|
|
482
|
+
* @stability unstable
|
|
483
|
+
* @category constructors
|
|
484
|
+
* @since 4.1.1
|
|
485
|
+
*/
|
|
486
|
+
export const importPrivate = Effect.fnUntraced(function*(
|
|
487
|
+
input: Redacted.Redacted<PrivateJwk>,
|
|
488
|
+
algorithm: AsymmetricAlgorithm
|
|
489
|
+
): Effect.fn.Return<PrivateKey, JoseError> {
|
|
490
|
+
const jwk = Redacted.value(input)
|
|
491
|
+
yield* checkMetadata(jwk, algorithm, "sig", ["sign"])
|
|
492
|
+
if (!isPrivateJwk(jwk)) return yield* invalidKey("Expected a private JWK with base64url key members")
|
|
493
|
+
const key = yield* KeyFormat.decodePrivate(KeyFormat.jwk, signatureAlgorithm(algorithm), jsonWebKey(jwk)).pipe(
|
|
494
|
+
Effect.mapError(cryptoFailure(`Could not import the private JWK for ${algorithm}`))
|
|
495
|
+
)
|
|
496
|
+
yield* checkModulus(key)
|
|
497
|
+
return { _tag: "PrivateKey", algorithm, kid: jwk.kid, key }
|
|
498
|
+
})
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Imports an SPKI public key from DER bytes or PEM text for an asymmetric algorithm.
|
|
502
|
+
*
|
|
503
|
+
* @see {@link importPublic} for importing JWK-encoded keys
|
|
504
|
+
* @see {@link exportSpki}
|
|
505
|
+
*
|
|
506
|
+
* @stability unstable
|
|
507
|
+
* @category constructors
|
|
508
|
+
* @since 4.1.1
|
|
509
|
+
*/
|
|
510
|
+
export const importSpki = Effect.fnUntraced(function*(
|
|
511
|
+
input: Uint8Array | string,
|
|
512
|
+
algorithm: AsymmetricAlgorithm,
|
|
513
|
+
options?: { readonly kid?: string | undefined }
|
|
514
|
+
): Effect.fn.Return<PublicKey, JoseError> {
|
|
515
|
+
const key = yield* KeyFormat.decodePublic<Signature.Algorithm, Uint8Array | string>(
|
|
516
|
+
typeof input === "string" ? KeyFormat.pem(KeyFormat.spki) : KeyFormat.spki,
|
|
517
|
+
signatureAlgorithm(algorithm),
|
|
518
|
+
input
|
|
519
|
+
).pipe(Effect.mapError(publicKeyFailure))
|
|
520
|
+
yield* checkModulus(key)
|
|
521
|
+
const jwk = yield* exportJwk(key, algorithm, options?.kid)
|
|
522
|
+
return { _tag: "PublicKey", algorithm, kid: options?.kid, jwk: jwk as PublicJwk, key }
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Imports a redacted PKCS#8 private key from DER bytes or PEM text for an asymmetric algorithm.
|
|
527
|
+
*
|
|
528
|
+
* @see {@link importPrivate} for importing JWK-encoded keys
|
|
529
|
+
* @see {@link exportPkcs8}
|
|
530
|
+
*
|
|
531
|
+
* @stability unstable
|
|
532
|
+
* @category constructors
|
|
533
|
+
* @since 4.1.1
|
|
534
|
+
*/
|
|
535
|
+
export const importPkcs8 = Effect.fnUntraced(function*(
|
|
536
|
+
input: Redacted.Redacted<Uint8Array | string>,
|
|
537
|
+
algorithm: AsymmetricAlgorithm,
|
|
538
|
+
options?: { readonly kid?: string | undefined }
|
|
539
|
+
): Effect.fn.Return<PrivateKey, JoseError> {
|
|
540
|
+
const data = Redacted.value(input)
|
|
541
|
+
const key = yield* KeyFormat.decodePrivate<Signature.Algorithm, Uint8Array | string>(
|
|
542
|
+
typeof data === "string" ? KeyFormat.pem(KeyFormat.pkcs8) : KeyFormat.pkcs8,
|
|
543
|
+
signatureAlgorithm(algorithm),
|
|
544
|
+
data
|
|
545
|
+
).pipe(Effect.mapError(cryptoFailure(`Could not import the PKCS#8 key for ${algorithm}`)))
|
|
546
|
+
yield* checkModulus(key)
|
|
547
|
+
return { _tag: "PrivateKey", algorithm, kid: options?.kid, key }
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Imports an octet JWK for HMAC signatures or for direct A256GCM encryption.
|
|
552
|
+
*
|
|
553
|
+
* **Details**
|
|
554
|
+
*
|
|
555
|
+
* HS256, HS384, and HS512 keys need at least 32, 48, and 64 bytes respectively;
|
|
556
|
+
* `dir` keys need exactly 32. Any `alg`,
|
|
557
|
+
* `use`, or `key_ops` member must allow the algorithm; `key_ops` must allow
|
|
558
|
+
* both of its operations.
|
|
559
|
+
*
|
|
560
|
+
* **Example** (Importing an HS256 key)
|
|
561
|
+
*
|
|
562
|
+
* ```ts import.meta.vitest
|
|
563
|
+
* import { Effect, Redacted } from "effect"
|
|
564
|
+
* import { Jwk } from "effect/jose"
|
|
565
|
+
*
|
|
566
|
+
* // Fixed public example material; generate application secrets securely.
|
|
567
|
+
* const secret = Redacted.make({ kty: "oct", k: "BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc" } as const)
|
|
568
|
+
* const key = await Effect.runPromise(Jwk.importSecret(secret, "HS256"))
|
|
569
|
+
* key.algorithm // => "HS256"
|
|
570
|
+
* ```
|
|
571
|
+
*
|
|
572
|
+
* @see {@link generateSecret}
|
|
573
|
+
*
|
|
574
|
+
* @stability unstable
|
|
575
|
+
* @category constructors
|
|
576
|
+
* @since 4.1.1
|
|
577
|
+
*/
|
|
578
|
+
export const importSecret = Effect.fnUntraced(function*<A extends SecretAlgorithm>(
|
|
579
|
+
input: Redacted.Redacted<SecretJwk>,
|
|
580
|
+
algorithm: A
|
|
581
|
+
): Effect.fn.Return<SecretKey<A>, JoseError> {
|
|
582
|
+
const jwk = Redacted.value(input)
|
|
583
|
+
if (algorithm !== "dir") {
|
|
584
|
+
yield* checkMetadata(jwk, algorithm, "sig", ["sign", "verify"])
|
|
585
|
+
} else {
|
|
586
|
+
yield* checkMetadata(jwk, algorithm, "enc", ["encrypt", "decrypt"])
|
|
587
|
+
}
|
|
588
|
+
const bytes = jwk.kty === "oct" ? decodeSegment(jwk.k) : undefined
|
|
589
|
+
if (bytes === undefined) return yield* invalidKey("Expected an oct JWK with a base64url k member")
|
|
590
|
+
const length = secretKeyLength(algorithm)
|
|
591
|
+
if (algorithm === "dir" ? bytes.length !== length : bytes.length < length) {
|
|
592
|
+
return yield* invalidKey(
|
|
593
|
+
algorithm === "dir"
|
|
594
|
+
? "dir keys must have exactly 32 bytes"
|
|
595
|
+
: `${algorithm} keys must have at least ${length} bytes`
|
|
596
|
+
)
|
|
597
|
+
}
|
|
598
|
+
const failure = cryptoFailure(`Could not import the ${algorithm} key`)
|
|
599
|
+
const key = algorithm !== "dir"
|
|
600
|
+
? yield* Effect.mapError(Mac.key(hmacAlgorithms[algorithm as HmacAlgorithm], bytes), failure)
|
|
601
|
+
: yield* Effect.mapError(Aead.key(Aead.aes256Gcm, bytes), failure)
|
|
602
|
+
return { _tag: "SecretKey", algorithm, kid: jwk.kid, key } as SecretKey<A>
|
|
603
|
+
})
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Exports a public key as a JWK carrying its `alg`, `kid`, and `use: "sig"`.
|
|
607
|
+
*
|
|
608
|
+
* @see {@link importPublic}
|
|
609
|
+
* @see {@link exportPrivate}
|
|
610
|
+
*
|
|
611
|
+
* @stability unstable
|
|
612
|
+
* @category encoding
|
|
613
|
+
* @since 4.1.1
|
|
614
|
+
*/
|
|
615
|
+
export const exportPublic = (key: PublicKey): Effect.Effect<PublicJwk, JoseError> =>
|
|
616
|
+
Effect.map(exportJwk(key.key, key.algorithm, key.kid), (jwk) => jwk as PublicJwk)
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Exports a private key as a JWK carrying its `alg`, `kid`, and `use: "sig"`.
|
|
620
|
+
*
|
|
621
|
+
* @see {@link importPrivate}
|
|
622
|
+
*
|
|
623
|
+
* @stability unstable
|
|
624
|
+
* @category encoding
|
|
625
|
+
* @since 4.1.1
|
|
626
|
+
*/
|
|
627
|
+
export const exportPrivate = (key: PrivateKey): Effect.Effect<Redacted.Redacted<PrivateJwk>, JoseError> =>
|
|
628
|
+
Effect.map(exportJwk(key.key, key.algorithm, key.kid), (jwk) => Redacted.make(jwk as PrivateJwk))
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Exports a public key as SPKI DER bytes, or as PEM text with `format: "pem"`.
|
|
632
|
+
*
|
|
633
|
+
* @see {@link importSpki}
|
|
634
|
+
* @see {@link exportPublic} for JWK output
|
|
635
|
+
*
|
|
636
|
+
* @stability unstable
|
|
637
|
+
* @category encoding
|
|
638
|
+
* @since 4.1.1
|
|
639
|
+
*/
|
|
640
|
+
export function exportSpki(
|
|
641
|
+
key: PublicKey,
|
|
642
|
+
options: { readonly format: "pem" }
|
|
643
|
+
): Effect.Effect<string, JoseError>
|
|
644
|
+
export function exportSpki(
|
|
645
|
+
key: PublicKey,
|
|
646
|
+
options?: { readonly format?: "der" | undefined }
|
|
647
|
+
): Effect.Effect<Uint8Array, JoseError>
|
|
648
|
+
export function exportSpki(
|
|
649
|
+
key: PublicKey,
|
|
650
|
+
options?: { readonly format?: "der" | "pem" | undefined }
|
|
651
|
+
): Effect.Effect<Uint8Array | string, JoseError>
|
|
652
|
+
export function exportSpki(
|
|
653
|
+
key: PublicKey,
|
|
654
|
+
options?: { readonly format?: "der" | "pem" | undefined }
|
|
655
|
+
): Effect.Effect<Uint8Array | string, JoseError> {
|
|
656
|
+
return KeyFormat.encode<KeyFormat.PublicKey, Uint8Array | string>(
|
|
657
|
+
options?.format === "pem" ? KeyFormat.pem(KeyFormat.spki) : KeyFormat.spki,
|
|
658
|
+
key.key as KeyFormat.PublicKey
|
|
659
|
+
).pipe(Effect.mapError(cryptoFailure("Could not export the SPKI key")))
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Exports a private key as redacted PKCS#8 DER bytes, or redacted PEM text with `format: "pem"`.
|
|
664
|
+
*
|
|
665
|
+
* @see {@link importPkcs8}
|
|
666
|
+
* @see {@link exportPrivate} for JWK output
|
|
667
|
+
*
|
|
668
|
+
* @stability unstable
|
|
669
|
+
* @category encoding
|
|
670
|
+
* @since 4.1.1
|
|
671
|
+
*/
|
|
672
|
+
export function exportPkcs8(
|
|
673
|
+
key: PrivateKey,
|
|
674
|
+
options: { readonly format: "pem" }
|
|
675
|
+
): Effect.Effect<Redacted.Redacted<string>, JoseError>
|
|
676
|
+
export function exportPkcs8(
|
|
677
|
+
key: PrivateKey,
|
|
678
|
+
options?: { readonly format?: "der" | undefined }
|
|
679
|
+
): Effect.Effect<Redacted.Redacted<Uint8Array>, JoseError>
|
|
680
|
+
export function exportPkcs8(
|
|
681
|
+
key: PrivateKey,
|
|
682
|
+
options?: { readonly format?: "der" | "pem" | undefined }
|
|
683
|
+
): Effect.Effect<Redacted.Redacted<Uint8Array | string>, JoseError>
|
|
684
|
+
export function exportPkcs8(
|
|
685
|
+
key: PrivateKey,
|
|
686
|
+
options?: { readonly format?: "der" | "pem" | undefined }
|
|
687
|
+
): Effect.Effect<Redacted.Redacted<Uint8Array | string>, JoseError> {
|
|
688
|
+
return KeyFormat.encode<KeyFormat.PrivateKey, Uint8Array | string>(
|
|
689
|
+
options?.format === "pem" ? KeyFormat.pem(KeyFormat.pkcs8) : KeyFormat.pkcs8,
|
|
690
|
+
key.key as KeyFormat.PrivateKey
|
|
691
|
+
).pipe(Effect.mapBoth({ onFailure: cryptoFailure("Could not export the PKCS#8 key"), onSuccess: Redacted.make }))
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* A JWK or imported key whose thumbprint can be computed. Private and secret
|
|
696
|
+
* JWKs must be redacted.
|
|
697
|
+
*
|
|
698
|
+
* @stability unstable
|
|
699
|
+
* @category models
|
|
700
|
+
* @since 4.1.1
|
|
701
|
+
*/
|
|
702
|
+
export type ThumbprintInput = PublicJwk | Redacted.Redacted<PrivateJwk | SecretJwk> | PublicKey | PrivateKey | SecretKey
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Computes an RFC 7638 JWK thumbprint, encoded as unpadded base64url.
|
|
706
|
+
*
|
|
707
|
+
* **Details**
|
|
708
|
+
*
|
|
709
|
+
* Uses SHA-256 by default; SHA-384 and SHA-512 are also supported. Only required
|
|
710
|
+
* key members are hashed, so metadata does not affect the result. Asymmetric
|
|
711
|
+
* private keys have the same thumbprint as their public keys. A secret key's
|
|
712
|
+
* thumbprint is a hash of the secret, so treat it as sensitive.
|
|
713
|
+
*
|
|
714
|
+
* @see {@link thumbprintUri}
|
|
715
|
+
*
|
|
716
|
+
* @stability unstable
|
|
717
|
+
* @category cryptography
|
|
718
|
+
* @since 4.1.1
|
|
719
|
+
*/
|
|
720
|
+
export const thumbprint = Effect.fnUntraced(function*(
|
|
721
|
+
input: ThumbprintInput,
|
|
722
|
+
hash: Digest.Algorithm = Digest.sha256
|
|
723
|
+
): Effect.fn.Return<string, JoseError, Digest.Digest> {
|
|
724
|
+
if (hash.name !== "SHA-256" && hash.name !== "SHA-384" && hash.name !== "SHA-512") {
|
|
725
|
+
return yield* invalidArgument("JWK thumbprints require SHA-256, SHA-384, or SHA-512")
|
|
726
|
+
}
|
|
727
|
+
const jwk = jsonWebKey(
|
|
728
|
+
Redacted.isRedacted(input) ? Redacted.value(input) : "kty" in input ?
|
|
729
|
+
input
|
|
730
|
+
: yield* KeyFormat.encode(KeyFormat.jwk, input.key as KeyFormat.Key).pipe(
|
|
731
|
+
Effect.mapError(cryptoFailure("Could not export the key for a thumbprint"))
|
|
732
|
+
)
|
|
733
|
+
)
|
|
734
|
+
let required: Record<string, string | undefined>
|
|
735
|
+
switch (jwk.kty) {
|
|
736
|
+
case "RSA":
|
|
737
|
+
required = { e: jwk.e, kty: jwk.kty, n: jwk.n }
|
|
738
|
+
break
|
|
739
|
+
case "EC":
|
|
740
|
+
required = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }
|
|
741
|
+
break
|
|
742
|
+
case "OKP":
|
|
743
|
+
required = { crv: jwk.crv, kty: jwk.kty, x: jwk.x }
|
|
744
|
+
break
|
|
745
|
+
case "oct":
|
|
746
|
+
required = { k: jwk.k, kty: jwk.kty }
|
|
747
|
+
break
|
|
748
|
+
default:
|
|
749
|
+
return yield* invalidKey("Unsupported JWK key type for a thumbprint")
|
|
750
|
+
}
|
|
751
|
+
if (
|
|
752
|
+
Object.values(required).some((value) => typeof value !== "string" || value.length === 0) ||
|
|
753
|
+
(required.kty === "oct" ? !isCanonicalSegment(required.k!) : !isPublicJwk(required))
|
|
754
|
+
) {
|
|
755
|
+
return yield* invalidKey("Expected a JWK with canonical base64url key members")
|
|
756
|
+
}
|
|
757
|
+
const digest = yield* Digest.Digest
|
|
758
|
+
return Base64Url.encode(yield* digest.digest(hash, utf8(JSON.stringify(required))))
|
|
759
|
+
})
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Computes an RFC 9278 JWK thumbprint URI using SHA-256 by default.
|
|
763
|
+
*
|
|
764
|
+
* @see {@link thumbprint} for supported inputs and hashes
|
|
765
|
+
*
|
|
766
|
+
* @stability unstable
|
|
767
|
+
* @category cryptography
|
|
768
|
+
* @since 4.1.1
|
|
769
|
+
*/
|
|
770
|
+
export const thumbprintUri = (
|
|
771
|
+
input: ThumbprintInput,
|
|
772
|
+
hash: Digest.Algorithm = Digest.sha256
|
|
773
|
+
): Effect.Effect<string, JoseError, Digest.Digest> =>
|
|
774
|
+
Effect.map(
|
|
775
|
+
thumbprint(input, hash),
|
|
776
|
+
(value) => `urn:ietf:params:oauth:jwk-thumbprint:${hash.name.toLowerCase()}:${value}`
|
|
777
|
+
)
|