plexus-protocol 0.6.0.0 → 0.7.0.0
raw patch · 8 files changed
+72/−197 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Plexus: SelectOption :: t -> Text -> Maybe Text -> SelectOption t
- Plexus: StreamRequest :: Text -> Provenance -> Text -> StandardRequest -> Maybe Int -> PlexusStreamItem
- Plexus: [itemRequestData] :: PlexusStreamItem -> StandardRequest
- Plexus: [itemRequestId] :: PlexusStreamItem -> Text
- Plexus: [itemTimeout] :: PlexusStreamItem -> Maybe Int
- Plexus: [methodBidirectional] :: MethodSchema -> Bool
- Plexus: [methodRequestType] :: MethodSchema -> Maybe Value
- Plexus: [methodResponseType] :: MethodSchema -> Maybe Value
- Plexus: [optionDescription] :: SelectOption t -> Maybe Text
- Plexus: [optionLabel] :: SelectOption t -> Text
- Plexus: [optionValue] :: SelectOption t -> t
- Plexus: data SelectOption t
- Plexus: sendBidirectionalResponse :: SubstrateConfig -> Text -> Response Value -> IO (Either TransportError ())
- Plexus: type StandardRequest = Request Value
- Plexus: type StandardResponse = Response Value
- Plexus.Schema.Recursive: [methodBidirectional] :: MethodSchema -> Bool
- Plexus.Schema.Recursive: [methodRequestType] :: MethodSchema -> Maybe Value
- Plexus.Schema.Recursive: [methodResponseType] :: MethodSchema -> Maybe Value
- Plexus.Transport: sendBidirectionalResponse :: SubstrateConfig -> Text -> Response Value -> IO (Either TransportError ())
- Plexus.Types: Cancelled :: Response t
- Plexus.Types: Confirm :: Text -> Maybe Bool -> Request t
- Plexus.Types: Confirmed :: Bool -> Response t
- Plexus.Types: Prompt :: Text -> Maybe t -> Maybe Text -> Request t
- Plexus.Types: Select :: Text -> [SelectOption t] -> Bool -> Request t
- Plexus.Types: SelectOption :: t -> Text -> Maybe Text -> SelectOption t
- Plexus.Types: Selected :: [t] -> Response t
- Plexus.Types: StreamRequest :: Text -> Provenance -> Text -> StandardRequest -> Maybe Int -> PlexusStreamItem
- Plexus.Types: Value :: t -> Response t
- Plexus.Types: [confirmDefault] :: Request t -> Maybe Bool
- Plexus.Types: [confirmMessage] :: Request t -> Text
- Plexus.Types: [confirmedValue] :: Response t -> Bool
- Plexus.Types: [itemRequestData] :: PlexusStreamItem -> StandardRequest
- Plexus.Types: [itemRequestId] :: PlexusStreamItem -> Text
- Plexus.Types: [itemTimeout] :: PlexusStreamItem -> Maybe Int
- Plexus.Types: [optionDescription] :: SelectOption t -> Maybe Text
- Plexus.Types: [optionLabel] :: SelectOption t -> Text
- Plexus.Types: [optionValue] :: SelectOption t -> t
- Plexus.Types: [promptDefault] :: Request t -> Maybe t
- Plexus.Types: [promptMessage] :: Request t -> Text
- Plexus.Types: [promptPlaceholder] :: Request t -> Maybe Text
- Plexus.Types: [responseValue] :: Response t -> t
- Plexus.Types: [selectMessage] :: Request t -> Text
- Plexus.Types: [selectMulti] :: Request t -> Bool
- Plexus.Types: [selectOptions] :: Request t -> [SelectOption t]
- Plexus.Types: [selectedValues] :: Response t -> [t]
- Plexus.Types: data Request t
- Plexus.Types: data Response t
- Plexus.Types: data SelectOption t
- Plexus.Types: instance Data.Aeson.Types.FromJSON.FromJSON t => Data.Aeson.Types.FromJSON.FromJSON (Plexus.Types.Request t)
- Plexus.Types: instance Data.Aeson.Types.FromJSON.FromJSON t => Data.Aeson.Types.FromJSON.FromJSON (Plexus.Types.Response t)
- Plexus.Types: instance Data.Aeson.Types.FromJSON.FromJSON t => Data.Aeson.Types.FromJSON.FromJSON (Plexus.Types.SelectOption t)
- Plexus.Types: instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Plexus.Types.Request t)
- Plexus.Types: instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Plexus.Types.Response t)
- Plexus.Types: instance Data.Aeson.Types.ToJSON.ToJSON t => Data.Aeson.Types.ToJSON.ToJSON (Plexus.Types.SelectOption t)
- Plexus.Types: instance GHC.Classes.Eq t => GHC.Classes.Eq (Plexus.Types.Request t)
- Plexus.Types: instance GHC.Classes.Eq t => GHC.Classes.Eq (Plexus.Types.Response t)
- Plexus.Types: instance GHC.Classes.Eq t => GHC.Classes.Eq (Plexus.Types.SelectOption t)
- Plexus.Types: instance GHC.Generics.Generic (Plexus.Types.Request t)
- Plexus.Types: instance GHC.Generics.Generic (Plexus.Types.Response t)
- Plexus.Types: instance GHC.Generics.Generic (Plexus.Types.SelectOption t)
- Plexus.Types: instance GHC.Show.Show t => GHC.Show.Show (Plexus.Types.Request t)
- Plexus.Types: instance GHC.Show.Show t => GHC.Show.Show (Plexus.Types.Response t)
- Plexus.Types: instance GHC.Show.Show t => GHC.Show.Show (Plexus.Types.SelectOption t)
- Plexus.Types: type StandardRequest = Request Value
- Plexus.Types: type StandardResponse = Response Value
- Plexus.Types: type WellKnownRequest = Request Value
- Plexus.Types: type WellKnownResponse = Response Value
- Plexus: MethodSchema :: Text -> Text -> PluginHash -> Maybe Value -> Value -> Maybe Value -> Maybe Value -> Cardinality -> Bool -> Text -> Maybe Value -> Maybe Value -> Maybe DeprecationInfo -> Maybe [ParamSchema] -> MethodRole -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe [Text] -> Bool -> Maybe Text -> [MethodExample] -> Maybe Value -> MethodSchema
+ Plexus: MethodSchema :: Text -> Text -> PluginHash -> Maybe Value -> Value -> Maybe Value -> Maybe Value -> Cardinality -> Text -> Maybe DeprecationInfo -> Maybe [ParamSchema] -> MethodRole -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe [Text] -> Bool -> Maybe Text -> [MethodExample] -> Maybe Value -> MethodSchema
- Plexus.Schema.Recursive: MethodSchema :: Text -> Text -> PluginHash -> Maybe Value -> Value -> Maybe Value -> Maybe Value -> Cardinality -> Bool -> Text -> Maybe Value -> Maybe Value -> Maybe DeprecationInfo -> Maybe [ParamSchema] -> MethodRole -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe [Text] -> Bool -> Maybe Text -> [MethodExample] -> Maybe Value -> MethodSchema
+ Plexus.Schema.Recursive: MethodSchema :: Text -> Text -> PluginHash -> Maybe Value -> Value -> Maybe Value -> Maybe Value -> Cardinality -> Text -> Maybe DeprecationInfo -> Maybe [ParamSchema] -> MethodRole -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe [Text] -> Bool -> Maybe Text -> [MethodExample] -> Maybe Value -> MethodSchema
Files
- CHANGELOG.md +19/−0
- README.md +1/−1
- plexus-protocol.cabal +1/−1
- src/Plexus.hs +0/−8
- src/Plexus/Schema/Recursive.hs +2/−9
- src/Plexus/Transport.hs +1/−19
- src/Plexus/Types.hs +1/−153
- test/Main.hs +47/−6
CHANGELOG.md view
@@ -1,5 +1,24 @@ # Changelog for plexus-protocol +## 0.7.0.0++bidir removed (ASK-1, ASK-3). Breaking.++### Breaking++- **bidir is gone.** The server no longer asks its caller mid-call: the+ `request` stream item (`StreamRequest`), `Request` / `Response`+ (`Confirm`, `Prompt`, `Select`; `Confirmed`, `Value`, `Selected`,+ `Cancelled`), `SelectOption`, `WellKnownRequest` / `WellKnownResponse`,+ `StandardRequest` / `StandardResponse` and `sendBidirectionalResponse`+ (`{ns}.respond`) are removed. A `request` item is no stream item.+- **`MethodSchema`**: `methodBidirectional`, `methodRequestType` and+ `methodResponseType` are removed, with nothing in their place. An older+ schema's `bidirectional` (and its request / response types) is read past.+- Plexus has no in-call or protocol-wide confirmation: a service that wants+ one builds it as its own methods. The input half (BIDIR-18,+ `Plexus.Input`) stays.+ ## 0.6.0.0 The Haskell side of plexus 0.7's schema and envelope. Breaking.
README.md view
@@ -188,7 +188,7 @@ , methodError :: Maybe Value -- JSON Schema of the error type E (fallible methods) , methodProgress :: Maybe Value -- JSON Schema of the progress type P , methodCardinality :: Cardinality -- CardinalityOne | CardinalityMany (required)- , … -- bidirectional, http_method, request/response types, deprecation, role+ , … -- http_method, deprecation, role, … } data SchemaResult
plexus-protocol.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: plexus-protocol-version: 0.6.0.0+version: 0.7.0.0 synopsis: Plexus RPC protocol types and client description: Haskell types and a client for Plexus RPC, a streaming JSON-RPC 2.0 protocol: stream items and provenance, recursive plugin and method
src/Plexus.hs view
@@ -54,14 +54,6 @@ , rpcCallStreaming , invokeMethodStreaming - -- * Bidirectional Response- , sendBidirectionalResponse-- -- * Bidirectional Types- , StandardRequest(..)- , StandardResponse(..)- , SelectOption(..)- -- * Stream Types , PlexusStreamItem(..) , Provenance(..)
src/Plexus/Schema/Recursive.hs view
@@ -246,10 +246,7 @@ , methodError :: Maybe Value -- ^ JSON Schema for the error type @E@ (@-> Result<T, E>@); 'Nothing' when the method is infallible , methodProgress :: Maybe Value -- ^ JSON Schema for the progress type @P@ carried by progress frames; 'Nothing' when the method reports no progress , methodCardinality :: Cardinality -- ^ One item or many- , methodBidirectional :: Bool -- ^ True if method uses a bidirectional channel , methodHttpMethod :: Text -- ^ HTTP method of the method's REST endpoint (@"GET"@, @"POST"@, …); @"POST"@ when absent- , methodRequestType :: Maybe Value -- ^ JSON Schema for the server→client request type (when bidirectional)- , methodResponseType :: Maybe Value -- ^ JSON Schema for the client→server response type (when bidirectional) , methodDeprecation :: Maybe DeprecationInfo -- ^ Deprecation info, if any (IR-5) , methodParamSchemas :: Maybe [ParamSchema] -- ^ Optional structured param info with per-field deprecations (IR-5) , methodRole :: MethodRole -- ^ Structural role in the activation graph (IR-2 / IR-3); defaults to 'MethodRoleRpc'@@ -275,10 +272,9 @@ <*> o .:? "error" <*> o .:? "progress" <*> cardinalityOf o- <*> o .:? "bidirectional" .!= False+ -- ASK-1: bidir is gone; an older schema's @bidirectional@,+ -- @request_type@ and @response_type@ are read past <*> o .:? "http_method" .!= "POST"- <*> o .:? "request_type"- <*> o .:? "response_type" <*> o .:? "deprecation" <*> o .:? "param_schemas" <*> o .:? "role" .!= MethodRoleRpc@@ -321,15 +317,12 @@ , "hash" .= methodHash , "returns" .= methodReturns , "cardinality" .= methodCardinality- , "bidirectional" .= methodBidirectional , "http_method" .= methodHttpMethod , "role" .= methodRole ] <> catMaybes [ "params" .=? methodParams , "error" .=? methodError , "progress" .=? methodProgress- , "request_type" .=? methodRequestType- , "response_type" .=? methodResponseType , "deprecation" .=? methodDeprecation , "param_schemas" .=? methodParamSchemas , "long_description" .=? methodLongDescription
src/Plexus/Transport.hs view
@@ -13,8 +13,6 @@ , invokeMethodStreamingWith , invokeMethodDuplex - -- * Bidirectional Response- , sendBidirectionalResponse -- * Schema Fetching , fetchSchemaAt@@ -50,7 +48,7 @@ import Plexus.Input (InputHalf) import Plexus.Client.Pool (ConnectionPool, createConnectionPool, withPooledConnection, defaultPlexusPoolConfig) import Plexus.RemoteError (renderRemoteError)-import Plexus.Types (PlexusStreamItem(..), TransportError(..), Response(..), StandardResponse)+import Plexus.Types (PlexusStreamItem(..), TransportError(..)) import Plexus.Schema.Recursive (PluginSchema, MethodSchema, SchemaResult(..), parsePluginSchema, parseSchemaResult) -- | Global connection pool cache@@ -291,19 +289,3 @@ let backend = substrateBackend cfg let callParams = object ["method" .= method, "params" .= params] rpcCallWith cfg (backend <> ".call") callParams---- | Send a response back to the server for a bidirectional request--- Uses {backend}.respond RPC method-sendBidirectionalResponse :: SubstrateConfig -> Text -> Response Value -> IO (Either TransportError ())-sendBidirectionalResponse cfg requestId response = do- let backend = substrateBackend cfg- let respondParams = object- [ "request_id" .= requestId- , "response_data" .= response- ]- result <- rpcCallWith cfg (backend <> ".respond") respondParams- case result of- Left transportErr -> pure $ Left transportErr- Right items -> case [renderRemoteError err | StreamError _ _ err _ <- items] of- (err:_) -> pure $ Left $ ProtocolError err- [] -> pure $ Right ()
src/Plexus/Types.hs view
@@ -22,15 +22,6 @@ , GuidanceSuggestion(..) , TransportError(..) - -- * Bidirectional Types- , SelectOption(..)- , Request(..)- , Response(..)- , WellKnownRequest- , WellKnownResponse- , StandardRequest -- Deprecated, kept for backwards compatibility- , StandardResponse -- Deprecated, kept for backwards compatibility- -- * Helpers , mkSubscribeRequest , mkUnsubscribeRequest@@ -369,125 +360,6 @@ _ -> fail $ "Unknown transport error_kind: " <> T.unpack kind -- ============================================================================--- Bidirectional Types (Request/Response)--- ============================================================================---- | Option for select requests, parameterized over value type-data SelectOption t = SelectOption- { optionValue :: t- , optionLabel :: Text- , optionDescription :: Maybe Text- }- deriving (Show, Eq, Generic)--instance (FromJSON t) => FromJSON (SelectOption t) where- parseJSON = withObject "SelectOption" $ \o -> SelectOption- <$> o .: "value"- <*> o .: "label"- <*> o .:? "description"--instance (ToJSON t) => ToJSON (SelectOption t) where- toJSON SelectOption{..} = object $- [ "value" .= optionValue, "label" .= optionLabel ]- <> catMaybes [("description" .=) <$> optionDescription]---- | Parameterized request type for bidirectional communication------ This type represents the well-known request types in the Plexus bidirectional protocol.--- Unlike Rust which uses traits, Haskell uses a parameterized ADT which provides--- similar flexibility with better type safety.------ The type parameter @t@ is used for values in Prompt defaults and Select options.--- For most cases, use 'WellKnownRequest' which sets @t = Value@.-data Request t- = Confirm { confirmMessage :: Text, confirmDefault :: Maybe Bool }- | Prompt { promptMessage :: Text, promptDefault :: Maybe t, promptPlaceholder :: Maybe Text }- | Select { selectMessage :: Text, selectOptions :: [SelectOption t], selectMulti :: Bool }- deriving (Show, Eq, Generic)---- | Well-known request types with JSON values------ This is the recommended type for most bidirectional requests.--- It matches the Rust @WellKnownRequest@ and TypeScript union types.-type WellKnownRequest = Request Value---- | Type alias for backwards compatibility: requests with JSON values------ Deprecated: Use 'WellKnownRequest' instead for consistency with Rust/TypeScript.-type StandardRequest = Request Value--instance (FromJSON t) => FromJSON (Request t) where- parseJSON = withObject "Request" $ \o -> do- typ <- o .: "type" :: Parser Text- case typ of- "confirm" -> Confirm- <$> o .: "message"- <*> o .:? "default"- "prompt" -> Prompt- <$> o .: "message"- <*> o .:? "default"- <*> o .:? "placeholder"- "select" -> Select- <$> o .: "message"- <*> o .: "options"- <*> o .:? "multi_select" .!= False- _ -> fail $ "Unknown request type: " <> T.unpack typ--instance (ToJSON t) => ToJSON (Request t) where- toJSON (Confirm msg def) = object $- [ "type" .= ("confirm" :: Text), "message" .= msg ]- <> catMaybes [("default" .=) <$> def]- toJSON (Prompt msg def placeholder) = object $- [ "type" .= ("prompt" :: Text), "message" .= msg ]- <> catMaybes [("default" .=) <$> def, ("placeholder" .=) <$> placeholder]- toJSON (Select msg opts multi) = object- [ "type" .= ("select" :: Text), "message" .= msg- , "options" .= opts, "multi_select" .= multi ]---- | Parameterized response type for bidirectional communication------ This type represents the well-known response types in the Plexus bidirectional protocol.------ Note: The 'Value' constructor corresponds to JSON @"type":"text"@ for--- wire compatibility with the Rust implementation.------ The type parameter @t@ is used for values in Prompt responses and Select responses.--- For most cases, use 'WellKnownResponse' which sets @t = Value@.-data Response t- = Confirmed { confirmedValue :: Bool }- | Value { responseValue :: t } -- ^ wire tag: "text"- | Selected { selectedValues :: [t] }- | Cancelled- deriving (Show, Eq, Generic)---- | Well-known response types with JSON values------ This is the recommended type for most bidirectional responses.--- It matches the Rust @WellKnownResponse@ and TypeScript union types.-type WellKnownResponse = Response Value---- | Type alias for backwards compatibility: responses with JSON values------ Deprecated: Use 'WellKnownResponse' instead for consistency with Rust/TypeScript.-type StandardResponse = Response Value--instance (FromJSON t) => FromJSON (Response t) where- parseJSON = withObject "Response" $ \o -> do- typ <- o .: "type" :: Parser Text- case typ of- "confirmed" -> Confirmed <$> o .: "value"- "text" -> Value <$> o .: "value"- "selected" -> Selected <$> o .: "values"- "cancelled" -> pure Cancelled- _ -> fail $ "Unknown response type: " <> T.unpack typ--instance (ToJSON t) => ToJSON (Response t) where- toJSON (Confirmed v) = object ["type" .= ("confirmed" :: Text), "value" .= v]- toJSON (Value v) = object ["type" .= ("text" :: Text), "value" .= v]- toJSON (Selected vs) = object ["type" .= ("selected" :: Text), "values" .= vs]- toJSON Cancelled = object ["type" .= ("cancelled" :: Text)]---- ============================================================================ -- Plexus Stream Items -- ============================================================================ @@ -545,13 +417,6 @@ -- the refusal's fields), kept as sent and written back so; empty -- for a frame built here. }- | StreamRequest- { itemPlexusHash :: Text- , itemProvenance :: Provenance- , itemRequestId :: Text- , itemRequestData :: StandardRequest- , itemTimeout :: Maybe Int- } | StreamDone { itemPlexusHash :: Text , itemProvenance :: Provenance@@ -565,7 +430,7 @@ pattern StreamError hash prov err rec <- StreamErrorWith hash prov err rec _ _ where StreamError hash prov err rec = StreamErrorWith hash prov err rec Nothing KM.empty -{-# COMPLETE StreamProgress, StreamData, StreamGuidance, StreamError, StreamRequest, StreamDone #-}+{-# COMPLETE StreamProgress, StreamData, StreamGuidance, StreamError, StreamDone #-} -- | AUTH-2: the refusal an item carries — an error item with -- @error_kind: "forbidden"@ (or whose typed error is a@@ -610,10 +475,6 @@ <*> o .: "recoverable" <*> pure (refusalFromObject o) <*> pure (besideError o)- "request" -> StreamRequest hash prov- <$> o .: "request_id"- <*> o .: "request"- <*> o .:? "timeout" "done" -> pure $ StreamDone hash prov _ -> fail $ "Unknown event type: " <> T.unpack typ @@ -644,11 +505,6 @@ <*> o .:? "recoverable" .!= False <*> pure (refusalFromObject o) <*> pure (besideError o)- "request" -> StreamRequest hash- <$> o .: "provenance"- <*> o .: "request_id"- <*> o .: "request"- <*> o .:? "timeout" "done" -> StreamDone hash <$> o .: "provenance" _ -> fail $ "Unknown event type: " <> T.unpack typ@@ -687,14 +543,6 @@ refusalFields = case toJSON <$> refusal of Just (Object ro) -> [ (k, v) | (k, v) <- KM.toList ro, k /= "message" ] _ -> []- toJSON (StreamRequest hash prov reqId reqData timeout) = object $- [ "type" .= ("request" :: Text)- , "metadata" .= StreamMetadata prov hash 0- , "request_id" .= reqId- , "request" .= reqData- ] <> catMaybes- [ ("timeout" .=) <$> timeout- ] toJSON (StreamDone hash prov) = object [ "type" .= ("done" :: Text) , "metadata" .= StreamMetadata prov hash 0
test/Main.hs view
@@ -1,4 +1,4 @@--- | plexus-protocol 0.6 against plexus 0.7.+-- | plexus-protocol 0.7 against plexus 0.7 and 0.8. -- -- The golden half reads RETURNS-7's conformance fixture by sibling path -- (@../plexus-macros/fixtures/conformance/expected/@) and checks that every@@ -101,6 +101,15 @@ matches (Array e) (Array a) = length e == length a && and (zipWith matches (toList e) (toList a)) matches e a = e == a +-- | ASK-1: a schema written before bidir's removal says+-- @"bidirectional": false@ on every method; it is read past and written as+-- nothing.+dropBidirectional :: Value -> Value+dropBidirectional = \case+ Object o -> Object (KM.map dropBidirectional (KM.filterWithKey (\k v -> not (k == "bidirectional" && v == Bool False)) o))+ Array a -> Array (fmap dropBidirectional a)+ v -> v+ -- | Parse @v@ as an @a@, re-encode it, and require the result to match @v@. roundTrips :: forall a. (FromJSON a, ToJSON a) => (Value -> Value) -> Value -> IO a roundTrips norm v = case parseEither parseJSON v of@@ -155,10 +164,12 @@ rejectionSpec strictnessSpec mergedSpec+ noBidirSpec schemaSpec :: Spec schemaSpec = describe "expected/schema.json" $ do- let load = readJson (fixtureDir </> "schema.json")+ -- ASK-1: a fixture written before bidir's removal says bidirectional: false+ let load = dropBidirectional <$> readJson (fixtureDir </> "schema.json") it "parses as a PluginSchema and re-encodes to the same JSON" $ do v <- load@@ -228,7 +239,6 @@ forM_ (psMethods schema) $ \m -> do methodHttpMethod m `shouldBe` "POST" methodRole m `shouldBe` MethodRoleRpc- methodBidirectional m `shouldBe` False wireSpec :: Spec wireSpec = describe "expected/wire/*.jsonl" $ do@@ -499,7 +509,7 @@ methodHttpMethod m `shouldBe` "POST" methodRole m `shouldBe` MethodRoleRpc toJSON m `shouldBe` method- [ returns, "cardinality" .= s "many", "bidirectional" .= False+ [ returns, "cardinality" .= s "many" , "http_method" .= s "POST", "role" .= object ["kind" .= s "rpc"] ] let meta = "metadata" .= object@@ -518,7 +528,7 @@ methodReturns one `shouldBe` object ["type" .= s "string"] -- written back in 0.8's shape toJSON many `shouldBe` method- [ returns, "cardinality" .= s "many", "bidirectional" .= False+ [ returns, "cardinality" .= s "many" , "http_method" .= s "POST", "role" .= object ["kind" .= s "rpc"] ] it "a 0.8 method's cardinality wins over a streaming flag beside it" $ do@@ -695,7 +705,7 @@ let wire = object [ "name" .= s "set_status", "description" .= s "d", "hash" .= s "h" , "returns" .= object [], "error" .= object ["title" .= s "SetStatusError"]- , "cardinality" .= s "one", "bidirectional" .= False, "http_method" .= s "POST"+ , "cardinality" .= s "one", "http_method" .= s "POST" , "role" .= object ["kind" .= s "rpc"] , "long_description" .= s "long", "grant" .= s "tickets.set_status", "target" .= s "id" , "held_on" .= [s "*"], "public" .= True, "group" .= s "write"@@ -721,3 +731,34 @@ (object ["namespace" .= s "menger", "methods" .= ([] :: [Value]), "view" .= s "anonymous"]) psHash p `shouldBe` "" psView p `shouldBe` Just Anonymous++-- | ASK-1: bidir is gone from the wire, and nothing replaced it: an older+-- schema's bidirectional keys are read past, and a request item is no stream+-- item.+noBidirSpec :: Spec+noBidirSpec = describe "no bidir (ASK-1)" $ do+ let method extra = object $+ [ "name" .= s "archive", "description" .= s "d", "hash" .= s "h"+ , "returns" .= object [], "cardinality" .= s "one" ] ++ extra+ meta = "metadata" .= object+ ["provenance" .= [s "tickets"], "plexus_hash" .= s "h", "timestamp" .= (0 :: Int)]++ it "an older schema's bidirectional (and its request/response types) is read past" $ do+ m <- either fail pure $ decodes @MethodSchema (method+ [ "bidirectional" .= True, "request_type" .= object ["title" .= s "StandardRequest"]+ , "response_type" .= object ["title" .= s "StandardResponse"] ])+ toJSON m `shouldBe` method ["http_method" .= s "POST", "role" .= object ["kind" .= s "rpc"]]++ it "a request item (spec/08's, gone) is no stream item" $+ (decodes @PlexusStreamItem (object+ [ "type" .= s "request", meta, "request_id" .= s "r1"+ , "request" .= object ["type" .= s "confirm", "message" .= s "ok?"] ]))+ `shouldSatisfy` either (const True) (const False)++ it "a data item whose content says needs_input is an ordinary data item" $ do+ let content = object ["type" .= s "needs_input", "summary" .= s "go", "token" .= s "t"]+ item <- roundTrips @PlexusStreamItem normalizeFrame (object+ [ "type" .= s "data", meta, "content_type" .= s "tickets.archive", "content" .= content ])+ case item of+ StreamData _ _ _ c -> c `shouldBe` content+ other -> expectationFailure ("not a data item: " <> show other)