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/Jwt.ts
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signed or encrypted compact JSON Web Tokens whose claims are encoded and
|
|
3
|
+
* decoded with a `Schema`.
|
|
4
|
+
*
|
|
5
|
+
* Verification and decryption authenticate the token first, then check the
|
|
6
|
+
* registered claims and the validation policy, and only then decode the
|
|
7
|
+
* application claims. `exp` and `nbf` are checked whenever they are present;
|
|
8
|
+
* require them with `requiredClaims`.
|
|
9
|
+
*
|
|
10
|
+
* Bound untrusted token length before verification, decryption, or unverified
|
|
11
|
+
* decoding; this module does not impose a token-size limit.
|
|
12
|
+
*
|
|
13
|
+
* @stability unstable
|
|
14
|
+
* @since 4.1.1
|
|
15
|
+
*/
|
|
16
|
+
import * as Clock from "../Clock.ts"
|
|
17
|
+
import type * as Aead from "../crypto/Aead.ts"
|
|
18
|
+
import type * as SecureRandom from "../crypto/SecureRandom.ts"
|
|
19
|
+
import type * as Signature from "../crypto/Signature.ts"
|
|
20
|
+
import type * as Duration from "../Duration.ts"
|
|
21
|
+
import * as Effect from "../Effect.ts"
|
|
22
|
+
import type * as Redacted from "../Redacted.ts"
|
|
23
|
+
import * as Schema from "../Schema.ts"
|
|
24
|
+
import { fail, invalidToken, millis, parseJsonObject, utf8 } from "./internal/compact.ts"
|
|
25
|
+
import * as JoseError from "./JoseError.ts"
|
|
26
|
+
import * as Jwe from "./Jwe.ts"
|
|
27
|
+
import type { PublicKey, SecretKey, SigningKey, VerificationKey } from "./Jwk.ts"
|
|
28
|
+
import type { Jwks } from "./Jwks.ts"
|
|
29
|
+
import * as Jws from "./Jws.ts"
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Schema for the registered claims: string `iss`, `sub`, and `jti`, a string
|
|
33
|
+
* or string array `aud`, and finite NumericDate `exp`, `nbf`, and `iat`.
|
|
34
|
+
*
|
|
35
|
+
* @stability unstable
|
|
36
|
+
* @category schemas
|
|
37
|
+
* @since 4.1.1
|
|
38
|
+
*/
|
|
39
|
+
export const RegisteredClaims = Schema.Struct({
|
|
40
|
+
iss: Schema.optionalKey(Schema.String),
|
|
41
|
+
sub: Schema.optionalKey(Schema.String),
|
|
42
|
+
aud: Schema.optionalKey(Schema.Union([Schema.String, Schema.Array(Schema.String)])),
|
|
43
|
+
exp: Schema.optionalKey(Schema.Finite),
|
|
44
|
+
nbf: Schema.optionalKey(Schema.Finite),
|
|
45
|
+
iat: Schema.optionalKey(Schema.Finite),
|
|
46
|
+
jti: Schema.optionalKey(Schema.String)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The registered claims of a JWT.
|
|
51
|
+
*
|
|
52
|
+
* @stability unstable
|
|
53
|
+
* @category models
|
|
54
|
+
* @since 4.1.1
|
|
55
|
+
*/
|
|
56
|
+
export type RegisteredClaims = typeof RegisteredClaims.Type
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The claim validation policy for a signed or encrypted JWT.
|
|
60
|
+
*
|
|
61
|
+
* @stability unstable
|
|
62
|
+
* @category models
|
|
63
|
+
* @since 4.1.1
|
|
64
|
+
*/
|
|
65
|
+
export interface VerifyOptions {
|
|
66
|
+
/**
|
|
67
|
+
* Accepted `iss` values.
|
|
68
|
+
*/
|
|
69
|
+
readonly issuer?: string | ReadonlyArray<string> | undefined
|
|
70
|
+
/**
|
|
71
|
+
* Accepted audiences. The token's `aud` must contain at least one.
|
|
72
|
+
*/
|
|
73
|
+
readonly audience?: string | ReadonlyArray<string> | undefined
|
|
74
|
+
readonly subject?: string | undefined
|
|
75
|
+
/**
|
|
76
|
+
* Expected `typ` header. Media types compare case-insensitively and without
|
|
77
|
+
* the `application/` prefix.
|
|
78
|
+
*/
|
|
79
|
+
readonly typ?: string | undefined
|
|
80
|
+
/**
|
|
81
|
+
* Tolerance for `exp`, `nbf`, and `iat`. Defaults to zero; numbers are
|
|
82
|
+
* milliseconds.
|
|
83
|
+
*/
|
|
84
|
+
readonly clockTolerance?: Duration.Input | undefined
|
|
85
|
+
/**
|
|
86
|
+
* Maximum age measured from `iat`, which becomes required. Numbers are
|
|
87
|
+
* milliseconds.
|
|
88
|
+
*/
|
|
89
|
+
readonly maxTokenAge?: Duration.Input | undefined
|
|
90
|
+
readonly requiredClaims?: ReadonlyArray<keyof RegisteredClaims> | undefined
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Options for {@link verifyWithKeySet}: the verification policy and the
|
|
95
|
+
* accepted algorithms.
|
|
96
|
+
*
|
|
97
|
+
* @stability unstable
|
|
98
|
+
* @category models
|
|
99
|
+
* @since 4.1.1
|
|
100
|
+
*/
|
|
101
|
+
export interface VerifyWithKeySetOptions extends VerifyOptions, Jws.VerifyWithKeySetOptions {}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* A verified JWT: decoded application claims, its registered claims, and the
|
|
105
|
+
* authenticated protected header.
|
|
106
|
+
*
|
|
107
|
+
* @stability unstable
|
|
108
|
+
* @category models
|
|
109
|
+
* @since 4.1.1
|
|
110
|
+
*/
|
|
111
|
+
export interface Verified<A, H = Jws.ProtectedHeader> {
|
|
112
|
+
readonly claims: A
|
|
113
|
+
readonly registeredClaims: RegisteredClaims
|
|
114
|
+
readonly protectedHeader: H
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A decrypted and validated JWT, with its protected header and decryption key.
|
|
119
|
+
*
|
|
120
|
+
* @stability unstable
|
|
121
|
+
* @category models
|
|
122
|
+
* @since 4.1.1
|
|
123
|
+
*/
|
|
124
|
+
export interface Decrypted<A> extends Verified<A, Jwe.ProtectedHeader> {
|
|
125
|
+
readonly key: SecretKey<"dir">
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The protected header and claims of a signed JWT that has not been verified.
|
|
130
|
+
*
|
|
131
|
+
* @stability unstable
|
|
132
|
+
* @category models
|
|
133
|
+
* @since 4.1.1
|
|
134
|
+
*/
|
|
135
|
+
export interface Unverified {
|
|
136
|
+
readonly protectedHeader: Jws.ProtectedHeader
|
|
137
|
+
readonly claims: Readonly<Record<string, Schema.Json>>
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Failures of JWT operations: JOSE failures, and schema failures while
|
|
142
|
+
* encoding or decoding the application claims.
|
|
143
|
+
*
|
|
144
|
+
* @stability unstable
|
|
145
|
+
* @category errors
|
|
146
|
+
* @since 4.1.1
|
|
147
|
+
*/
|
|
148
|
+
export type JwtError = JoseError.JoseError | Schema.SchemaError
|
|
149
|
+
|
|
150
|
+
const claimValidationFailed = (
|
|
151
|
+
claim: JoseError.ClaimValidationFailed["claim"],
|
|
152
|
+
reason: JoseError.ClaimValidationFailed["reason"]
|
|
153
|
+
) => fail(new JoseError.ClaimValidationFailed({ claim, reason }))
|
|
154
|
+
|
|
155
|
+
// Each claim is checked on its own so the failure can name it.
|
|
156
|
+
const registeredClaimGuards = Object.entries(RegisteredClaims.fields).map(([name, field]) =>
|
|
157
|
+
[name as keyof RegisteredClaims, Schema.is(field.schema)] as const
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
interface Policy extends Omit<VerifyOptions, "clockTolerance" | "maxTokenAge"> {
|
|
161
|
+
readonly clockTolerance: number
|
|
162
|
+
readonly maxTokenAge: number | undefined
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Durations are read before any cryptography, in seconds.
|
|
166
|
+
const readPolicy = Effect.fnUntraced(function*(
|
|
167
|
+
options: VerifyOptions | undefined
|
|
168
|
+
): Effect.fn.Return<Policy, JoseError.JoseError> {
|
|
169
|
+
const clockTolerance = options?.clockTolerance === undefined
|
|
170
|
+
? 0
|
|
171
|
+
: yield* millis("clockTolerance", options.clockTolerance)
|
|
172
|
+
const maxTokenAge = options?.maxTokenAge === undefined ? undefined : yield* millis("maxTokenAge", options.maxTokenAge)
|
|
173
|
+
return {
|
|
174
|
+
...options,
|
|
175
|
+
clockTolerance: clockTolerance / 1000,
|
|
176
|
+
maxTokenAge: maxTokenAge === undefined ? undefined : maxTokenAge / 1000
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const toArray = (value: string | ReadonlyArray<string>): ReadonlyArray<string> =>
|
|
181
|
+
typeof value === "string" ? [value] : value
|
|
182
|
+
|
|
183
|
+
const mediaType = (value: string): string => {
|
|
184
|
+
const type = value.toLowerCase()
|
|
185
|
+
return type.includes("/") ? type : `application/${type}`
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const checkClaims = Effect.fnUntraced(function*(
|
|
189
|
+
claims: Readonly<Record<string, Schema.Json>>,
|
|
190
|
+
header: { readonly typ?: string | undefined },
|
|
191
|
+
policy: Policy
|
|
192
|
+
): Effect.fn.Return<RegisteredClaims, JoseError.JoseError> {
|
|
193
|
+
const registered: Record<string, unknown> = {}
|
|
194
|
+
for (const [name, isValid] of registeredClaimGuards) {
|
|
195
|
+
if (!Object.hasOwn(claims, name)) continue
|
|
196
|
+
if (!isValid(claims[name])) return yield* claimValidationFailed(name, "invalid")
|
|
197
|
+
registered[name] = claims[name]
|
|
198
|
+
}
|
|
199
|
+
const { iss, sub, aud, exp, nbf, iat } = registered as RegisteredClaims
|
|
200
|
+
|
|
201
|
+
for (const name of policy.requiredClaims ?? []) {
|
|
202
|
+
if (registered[name] === undefined) return yield* claimValidationFailed(name, "missing")
|
|
203
|
+
}
|
|
204
|
+
if (policy.issuer !== undefined) {
|
|
205
|
+
if (iss === undefined) return yield* claimValidationFailed("iss", "missing")
|
|
206
|
+
if (!toArray(policy.issuer).includes(iss)) return yield* claimValidationFailed("iss", "mismatch")
|
|
207
|
+
}
|
|
208
|
+
if (policy.subject !== undefined) {
|
|
209
|
+
if (sub === undefined) return yield* claimValidationFailed("sub", "missing")
|
|
210
|
+
if (sub !== policy.subject) return yield* claimValidationFailed("sub", "mismatch")
|
|
211
|
+
}
|
|
212
|
+
if (policy.audience !== undefined) {
|
|
213
|
+
if (aud === undefined) return yield* claimValidationFailed("aud", "missing")
|
|
214
|
+
const audiences = toArray(aud)
|
|
215
|
+
if (!toArray(policy.audience).some((audience) => audiences.includes(audience))) {
|
|
216
|
+
return yield* claimValidationFailed("aud", "mismatch")
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (policy.typ !== undefined && (header.typ === undefined || mediaType(header.typ) !== mediaType(policy.typ))) {
|
|
220
|
+
return yield* claimValidationFailed("typ", "mismatch")
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const now = Math.floor((yield* Clock.currentTimeMillis) / 1000)
|
|
224
|
+
const tolerance = policy.clockTolerance
|
|
225
|
+
if (exp !== undefined && exp <= now - tolerance) return yield* claimValidationFailed("exp", "expired")
|
|
226
|
+
if (nbf !== undefined && nbf > now + tolerance) return yield* claimValidationFailed("nbf", "notYetValid")
|
|
227
|
+
if (policy.maxTokenAge !== undefined) {
|
|
228
|
+
if (iat === undefined) return yield* claimValidationFailed("iat", "missing")
|
|
229
|
+
if (iat > now + tolerance) return yield* claimValidationFailed("iat", "future")
|
|
230
|
+
if (now - iat - tolerance > policy.maxTokenAge) return yield* claimValidationFailed("iat", "tooOld")
|
|
231
|
+
}
|
|
232
|
+
return registered as RegisteredClaims
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
const decodeClaims = Effect.fnUntraced(function*<
|
|
236
|
+
S extends Schema.Constraint,
|
|
237
|
+
H extends Jws.ProtectedHeader | Jwe.ProtectedHeader
|
|
238
|
+
>(
|
|
239
|
+
schema: S,
|
|
240
|
+
payload: Uint8Array,
|
|
241
|
+
protectedHeader: H,
|
|
242
|
+
policy: Policy
|
|
243
|
+
): Effect.fn.Return<Verified<S["Type"], H>, JwtError, S["DecodingServices"]> {
|
|
244
|
+
const claims = parseJsonObject(payload)
|
|
245
|
+
if (claims === undefined) return yield* invalidToken("The JWT payload is not a JSON object")
|
|
246
|
+
const registeredClaims = yield* checkClaims(claims, protectedHeader, policy)
|
|
247
|
+
return {
|
|
248
|
+
claims: yield* Schema.decodeUnknownEffect(schema)(claims),
|
|
249
|
+
registeredClaims,
|
|
250
|
+
protectedHeader
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
const decodeClaimsJson = Schema.decodeUnknownEffect(
|
|
255
|
+
Schema.JsonObject.check(Schema.makeFilter((claims) => Schema.is(RegisteredClaims)(claims)))
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
const encodeClaims = Effect.fnUntraced(function*<S extends Schema.Constraint>(
|
|
259
|
+
schema: S,
|
|
260
|
+
claims: S["Type"]
|
|
261
|
+
): Effect.fn.Return<Uint8Array, Schema.SchemaError, S["EncodingServices"]> {
|
|
262
|
+
const encoded = yield* Schema.encodeEffect(schema)(claims)
|
|
263
|
+
const json = yield* decodeClaimsJson(encoded)
|
|
264
|
+
return utf8(JSON.stringify(json))
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Encodes claims with a schema and signs them as a compact JWT.
|
|
269
|
+
*
|
|
270
|
+
* **Details**
|
|
271
|
+
*
|
|
272
|
+
* The encoded claims must be a JSON object whose registered claims match
|
|
273
|
+
* {@link RegisteredClaims}.
|
|
274
|
+
*
|
|
275
|
+
* @see {@link verify}
|
|
276
|
+
* @see {@link encrypt} for encrypted JWTs
|
|
277
|
+
*
|
|
278
|
+
* @stability unstable
|
|
279
|
+
* @category cryptography
|
|
280
|
+
* @since 4.1.1
|
|
281
|
+
*/
|
|
282
|
+
export const sign = <
|
|
283
|
+
S extends Schema.Constraint,
|
|
284
|
+
K extends SigningKey,
|
|
285
|
+
H extends object & { readonly [P in keyof H]: Schema.Json | undefined } = Jws.Header
|
|
286
|
+
>(
|
|
287
|
+
schema: S,
|
|
288
|
+
claims: S["Type"],
|
|
289
|
+
key: K,
|
|
290
|
+
header?: Jws.Header & H
|
|
291
|
+
): Effect.Effect<Redacted.Redacted<string>, JwtError, S["EncodingServices"] | Jws.KeyRequirements<K>> =>
|
|
292
|
+
Effect.flatMap(encodeClaims(schema, claims), (payload) => Jws.sign(payload, key, header))
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Verifies a compact JWT with a key, checks its claims against the policy, and
|
|
296
|
+
* decodes the claims with a schema.
|
|
297
|
+
*
|
|
298
|
+
* **Example** (Verifying a token)
|
|
299
|
+
*
|
|
300
|
+
* ```ts import.meta.vitest
|
|
301
|
+
* import { Effect, Layer, Redacted, Schema } from "effect"
|
|
302
|
+
* import { Mac, SecureRandom, Signature } from "effect/crypto"
|
|
303
|
+
* import { Jwk, Jwt } from "effect/jose"
|
|
304
|
+
*
|
|
305
|
+
* const layer = Layer.mergeAll(Mac.layerWebCrypto, Signature.layerWebCrypto).pipe(
|
|
306
|
+
* Layer.provide(SecureRandom.layerWebCrypto)
|
|
307
|
+
* )
|
|
308
|
+
*
|
|
309
|
+
* const Claims = Schema.Struct({ sub: Schema.String, iss: Schema.String })
|
|
310
|
+
*
|
|
311
|
+
* const claims = await Effect.runPromise(Effect.gen(function*() {
|
|
312
|
+
* // Fixed public example material; generate application secrets securely.
|
|
313
|
+
* const key = yield* Jwk.importSecret(
|
|
314
|
+
* Redacted.make({ kty: "oct", k: "BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc" } as const),
|
|
315
|
+
* "HS256"
|
|
316
|
+
* )
|
|
317
|
+
* const token = yield* Jwt.sign(Claims, { sub: "user-123", iss: "example" }, key)
|
|
318
|
+
* const verified = yield* Jwt.verify(Claims, token, key, { issuer: "example", requiredClaims: ["sub"] })
|
|
319
|
+
* return verified.claims
|
|
320
|
+
* }).pipe(Effect.provide(layer)))
|
|
321
|
+
* claims // => ({ sub: "user-123", iss: "example" })
|
|
322
|
+
* ```
|
|
323
|
+
*
|
|
324
|
+
* @see {@link verifyWithKeySet} for resolving the key from the `Jwks` service
|
|
325
|
+
* @see {@link decrypt} for encrypted JWTs
|
|
326
|
+
*
|
|
327
|
+
* @stability unstable
|
|
328
|
+
* @category cryptography
|
|
329
|
+
* @since 4.1.1
|
|
330
|
+
*/
|
|
331
|
+
export const verify: <S extends Schema.Constraint, K extends VerificationKey>(
|
|
332
|
+
schema: S,
|
|
333
|
+
token: string | Redacted.Redacted<string>,
|
|
334
|
+
key: K,
|
|
335
|
+
options?: VerifyOptions
|
|
336
|
+
) => Effect.Effect<
|
|
337
|
+
Verified<S["Type"]>,
|
|
338
|
+
JwtError,
|
|
339
|
+
S["DecodingServices"] | Jws.KeyRequirements<K>
|
|
340
|
+
> = Effect.fnUntraced(function*<S extends Schema.Constraint, K extends VerificationKey>(
|
|
341
|
+
schema: S,
|
|
342
|
+
token: string | Redacted.Redacted<string>,
|
|
343
|
+
key: K,
|
|
344
|
+
options?: VerifyOptions
|
|
345
|
+
): Effect.fn.Return<Verified<S["Type"]>, JwtError, S["DecodingServices"] | Jws.KeyRequirements<K>> {
|
|
346
|
+
const policy = yield* readPolicy(options)
|
|
347
|
+
const verified = yield* Jws.verify(token, key)
|
|
348
|
+
return yield* decodeClaims(schema, verified.payload, verified.protectedHeader, policy)
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Verifies a compact JWT with a public key resolved from the `Jwks` service,
|
|
353
|
+
* checks its claims against the policy, and decodes the claims with a schema.
|
|
354
|
+
*
|
|
355
|
+
* @see {@link verify} for verifying with a known key
|
|
356
|
+
*
|
|
357
|
+
* @stability unstable
|
|
358
|
+
* @category cryptography
|
|
359
|
+
* @since 4.1.1
|
|
360
|
+
*/
|
|
361
|
+
export const verifyWithKeySet: <S extends Schema.Constraint>(
|
|
362
|
+
schema: S,
|
|
363
|
+
token: string | Redacted.Redacted<string>,
|
|
364
|
+
options: VerifyWithKeySetOptions
|
|
365
|
+
) => Effect.Effect<
|
|
366
|
+
Verified<S["Type"]> & { readonly key: PublicKey },
|
|
367
|
+
JwtError,
|
|
368
|
+
S["DecodingServices"] | Jwks | Signature.Signature
|
|
369
|
+
> = Effect.fnUntraced(function*<S extends Schema.Constraint>(
|
|
370
|
+
schema: S,
|
|
371
|
+
token: string | Redacted.Redacted<string>,
|
|
372
|
+
options: VerifyWithKeySetOptions
|
|
373
|
+
): Effect.fn.Return<
|
|
374
|
+
Verified<S["Type"]> & { readonly key: PublicKey },
|
|
375
|
+
JwtError,
|
|
376
|
+
S["DecodingServices"] | Jwks | Signature.Signature
|
|
377
|
+
> {
|
|
378
|
+
const policy = yield* readPolicy(options)
|
|
379
|
+
const verified = yield* Jws.verifyWithKeySet(token, options)
|
|
380
|
+
return {
|
|
381
|
+
...(yield* decodeClaims(schema, verified.payload, verified.protectedHeader, policy)),
|
|
382
|
+
key: verified.key
|
|
383
|
+
}
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Encodes claims with a schema and encrypts them as a compact `dir`/A256GCM
|
|
388
|
+
* JWT.
|
|
389
|
+
*
|
|
390
|
+
* **Details**
|
|
391
|
+
*
|
|
392
|
+
* The encoded claims must be a JSON object whose registered claims match
|
|
393
|
+
* {@link RegisteredClaims}.
|
|
394
|
+
*
|
|
395
|
+
* **Example** (Encrypting and validating application claims)
|
|
396
|
+
*
|
|
397
|
+
* ```ts import.meta.vitest
|
|
398
|
+
* import { Effect, Layer, Redacted, Schema } from "effect"
|
|
399
|
+
* import { Aead, SecureRandom } from "effect/crypto"
|
|
400
|
+
* import { Jwk, Jwt } from "effect/jose"
|
|
401
|
+
*
|
|
402
|
+
* const layer = Aead.layerWebCrypto.pipe(Layer.provideMerge(SecureRandom.layerWebCrypto))
|
|
403
|
+
* const Claims = Schema.Struct({ sub: Schema.String })
|
|
404
|
+
*
|
|
405
|
+
* const claims = await Effect.runPromise(Effect.gen(function*() {
|
|
406
|
+
* // Fixed public example material; generate application secrets securely.
|
|
407
|
+
* const key = yield* Jwk.importSecret(
|
|
408
|
+
* Redacted.make({ kty: "oct", k: "BwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwc" } as const),
|
|
409
|
+
* "dir"
|
|
410
|
+
* )
|
|
411
|
+
* const token = yield* Jwt.encrypt(Claims, { sub: "user-123" }, key, { typ: "session+jwt" })
|
|
412
|
+
* const decrypted = yield* Jwt.decrypt(Claims, token, key, { typ: "session+jwt" })
|
|
413
|
+
* return decrypted.claims
|
|
414
|
+
* }).pipe(Effect.provide(layer)))
|
|
415
|
+
* claims // => ({ sub: "user-123" })
|
|
416
|
+
* ```
|
|
417
|
+
*
|
|
418
|
+
* @see {@link decrypt}
|
|
419
|
+
* @see {@link sign} for signed JWTs
|
|
420
|
+
*
|
|
421
|
+
* @stability unstable
|
|
422
|
+
* @category cryptography
|
|
423
|
+
* @since 4.1.1
|
|
424
|
+
*/
|
|
425
|
+
export const encrypt = <
|
|
426
|
+
S extends Schema.Constraint,
|
|
427
|
+
H extends object & { readonly [P in keyof H]: Schema.Json | undefined } = Jwe.Header
|
|
428
|
+
>(
|
|
429
|
+
schema: S,
|
|
430
|
+
claims: S["Type"],
|
|
431
|
+
key: SecretKey<"dir">,
|
|
432
|
+
header?: Jwe.Header & H
|
|
433
|
+
): Effect.Effect<Redacted.Redacted<string>, JwtError, S["EncodingServices"] | Aead.Aead | SecureRandom.SecureRandom> =>
|
|
434
|
+
Effect.flatMap(encodeClaims(schema, claims), (payload) => Jwe.encrypt(payload, key, header))
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Decrypts a compact `dir`/A256GCM JWT, checks its claims against the policy,
|
|
438
|
+
* and decodes the claims with a schema.
|
|
439
|
+
*
|
|
440
|
+
* **Details**
|
|
441
|
+
*
|
|
442
|
+
* Accepts a key or an effectful resolver for key rotation. The same claim
|
|
443
|
+
* policy as {@link verify} is applied after authenticated decryption and
|
|
444
|
+
* before the application schema is decoded.
|
|
445
|
+
*
|
|
446
|
+
* **Gotchas**
|
|
447
|
+
*
|
|
448
|
+
* The resolver receives an unauthenticated header and must use it only for
|
|
449
|
+
* key selection.
|
|
450
|
+
*
|
|
451
|
+
* @see {@link encrypt}
|
|
452
|
+
* @see {@link verify} for signed JWTs
|
|
453
|
+
*
|
|
454
|
+
* @stability unstable
|
|
455
|
+
* @category cryptography
|
|
456
|
+
* @since 4.1.1
|
|
457
|
+
*/
|
|
458
|
+
export const decrypt = Effect.fnUntraced(function*<S extends Schema.Constraint, E = never, R = never>(
|
|
459
|
+
schema: S,
|
|
460
|
+
token: string | Redacted.Redacted<string>,
|
|
461
|
+
key: SecretKey<"dir"> | ((header: Jwe.ProtectedHeader) => Effect.Effect<SecretKey<"dir">, E, R>),
|
|
462
|
+
options?: VerifyOptions
|
|
463
|
+
): Effect.fn.Return<Decrypted<S["Type"]>, JwtError | E, S["DecodingServices"] | Aead.Aead | R> {
|
|
464
|
+
const policy = yield* readPolicy(options)
|
|
465
|
+
const decrypted = yield* Jwe.decrypt(token, key)
|
|
466
|
+
return {
|
|
467
|
+
...(yield* decodeClaims(schema, decrypted.plaintext, decrypted.protectedHeader, policy)),
|
|
468
|
+
key: decrypted.key
|
|
469
|
+
}
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Reads the protected header and claims of a signed JWT without verifying it.
|
|
474
|
+
*
|
|
475
|
+
* **Gotchas**
|
|
476
|
+
*
|
|
477
|
+
* Nothing returned here is authenticated. Use it only to choose how to
|
|
478
|
+
* verify, never to authorize.
|
|
479
|
+
*
|
|
480
|
+
* @see {@link verify}
|
|
481
|
+
*
|
|
482
|
+
* @stability unstable
|
|
483
|
+
* @category decoding
|
|
484
|
+
* @since 4.1.1
|
|
485
|
+
*/
|
|
486
|
+
export const decodeUnverified = Effect.fnUntraced(function*(
|
|
487
|
+
token: string | Redacted.Redacted<string>
|
|
488
|
+
): Effect.fn.Return<Unverified, JoseError.JoseError> {
|
|
489
|
+
const parsed = yield* Jws.parse(token)
|
|
490
|
+
const claims = parseJsonObject(parsed.payload)
|
|
491
|
+
if (claims === undefined) return yield* invalidToken("The JWT payload is not a JSON object")
|
|
492
|
+
return { protectedHeader: parsed.protectedHeader, claims }
|
|
493
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JOSE keys, key sets, signatures, encryption, and schema-typed JSON Web Tokens.
|
|
3
|
+
*
|
|
4
|
+
* `Jwk` imports and exports JSON Web Keys; `Jwks` resolves keys from JSON Web
|
|
5
|
+
* Key Sets. `Jws`, `Jwe`, and `Jwt` handle JSON Web Signatures, JSON Web
|
|
6
|
+
* Encryption, and JSON Web Tokens respectively.
|
|
7
|
+
*
|
|
8
|
+
* The supported profile is compact serialization with HS256/384/512,
|
|
9
|
+
* RS256/384/512, PS256/384/512, ES256/384/512 (P-256/P-384/P-521), and EdDSA
|
|
10
|
+
* (Ed25519) signatures, and `dir`/A256GCM encryption.
|
|
11
|
+
* Other algorithms and JSON serializations are outside this profile.
|
|
12
|
+
* `Jwk` also generates symmetric keys, computes JWK thumbprints, and imports
|
|
13
|
+
* and exports SPKI and PKCS#8 keys in DER or PEM form.
|
|
14
|
+
*
|
|
15
|
+
* Apply an application-specific token-length limit before verification,
|
|
16
|
+
* decryption, or unverified decoding.
|
|
17
|
+
*
|
|
18
|
+
* @stability unstable
|
|
19
|
+
* @since 4.1.1
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// @barrel
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @stability unstable
|
|
26
|
+
* @since 4.1.1
|
|
27
|
+
*/
|
|
28
|
+
export * as JoseError from "./JoseError.ts"
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @stability unstable
|
|
32
|
+
* @since 4.1.1
|
|
33
|
+
*/
|
|
34
|
+
export * as Jwe from "./Jwe.ts"
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @stability unstable
|
|
38
|
+
* @since 4.1.1
|
|
39
|
+
*/
|
|
40
|
+
export * as Jwk from "./Jwk.ts"
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @stability unstable
|
|
44
|
+
* @since 4.1.1
|
|
45
|
+
*/
|
|
46
|
+
export * as Jwks from "./Jwks.ts"
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @stability unstable
|
|
50
|
+
* @since 4.1.1
|
|
51
|
+
*/
|
|
52
|
+
export * as Jws from "./Jws.ts"
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @stability unstable
|
|
56
|
+
* @since 4.1.1
|
|
57
|
+
*/
|
|
58
|
+
export * as Jwt from "./Jwt.ts"
|