hyperledger / aries-cloudagent-python

Hyperledger Aries Cloud Agent Python (ACA-Py) is a foundation for building decentralized identity applications and services running in non-mobile environments.
https://wiki.hyperledger.org/display/aries
Apache License 2.0
406 stars 510 forks source link

Suggestion: Add OpenAPI doc for Administration API Webhooks #1503

Open eliasschoof opened 2 years ago

eliasschoof commented 2 years ago

I am developing an Aries controller in TypeScript. The OpenAPI doc for the Administration API is very useful as a template when creating request and response types.

Would it be possible to also provide an OpenAPI doc for the Administration API Webhooks? That is, an OpenAPI specification of the Webhook API expected by the Aries agent?

So far I have only managed to find the prose description in the Administration API documentation.

swcurran commented 2 years ago

Good question. AFAIK, the Web Hook API is higher level in that there is not a specific definition per message type in all protocols. Maybe that's a good thing -- maybe not. If we have to have per protocol endpoints on the Admin API side, why not on the web hook side?

That said -- I'm not up to date on the precise state of the webhooks. @ianco @shaangill025 -- thoughts on this? @jcourt562 ?

ianco commented 2 years ago

There is one webhook endpoint, but the webhook URL that is actually called by aca-py will contain the <topic>, which is basically the message type. The payload is basically the protocol state and attached message (whatever message is received at that stage of the protocol, as far as I recall offhand). The attached message may be different per protocol state. I don't think aca-py expects any response, other than HTTP status 200 for success (if the HTTP status reports an error, aca-py will retry the webhook, but it won't impact the execution of the protocol).

In your controller, you can define one endpoint with the <topic> as a dynamic parameter, or a separate endpoint per protocol.

eliasschoof commented 2 years ago

Thanks @ianco! So far I implemented an endpoint for /topic/connections. From experimentation I figured that the Aries agent seems to send payloads of type ConnRecord to that endpoint (as defined in the Admin API spec). But from your comment I gather that the payload could be basically anything that comes up in any connections-related protocol?

My goal is to notify the user whenever the Aries agent receives an invitation. I was planning to check the payloads sent to my /topic/connections webhook and filter for received invitations. But that is difficult if the payload could basically be anything...

ianco commented 2 years ago

I believe the webhook payload will include the message received at that stage of the protocol. So it's not "basically anything", because all the messages are defined in the respective RFC's.

I agree the docs for webhooks could be better :-( ... There is an example of a generic approach to handling webhooks in the alice/faber demo - the endpoint is defined here: https://github.com/hyperledger/aries-cloudagent-python/blob/main/demo/runners/support/agent.py#L683 and then handler method is just below this in the code

jcourt562 commented 2 years ago

My understanding corresponds with Ian. Unfortunately it is only a read understanding atm. A hook server is the next on my list of things to add to the MacOS SDK we release along with persistent postgres DB configuration.

So the other thing to realise is that OpenAPI is about REST API description/definition. ACA-py calls the API that should be defined all be it, really it is defining what it expects to see. You couldn't implement a Swagger UI to it in ACA-py because there is nothing backing what that definition is presenting (i.e. the implementation lives on the Hook Server not ACA-py).

So my expectation is that the Hook Server implementation should present the OpenAPI spec, at least that is my intention. Whether you could create a generic Hook Server as a part of Aries is an interesting question but there is a lot of business logic likely to need to exist in such a process.

Hope this helps and I haven't added to any confusion.

eliasschoof commented 2 years ago

@jcourt562 I agree that the Webhook API lives on the controller server and not ACA-py. But in my view an OpenAPI specification would make the life of webhook developers so much easier.

An example where the OpenAPI documentation would be helpful. Say I have a webhook for /topic/connections, check the incoming payloads for state === 'active' and trigger some business logic if the condition is satisfied. Now suppose I update to a new version of ACA-py and want to figure out if this approach still works. Why might it now work? Maybe after the update payloads are wrapped into something like {data: {...}}, maybe the field was renamed from state to currentState, maybe the field was deprecated and I need to use rfc23_state instead...

If ACA-py shipped with an OpenAPI specification for the Webhook API, I could just check the specification and convince myself that state is still there (or not). Without the specification this is much more difficult.

swcurran commented 2 years ago

I agree that it would be good to have. I think it is a bootstrapping / maintenance problem. The Admin API has to have an OpenAPI specification, where as we could get away with the webhook being "just an endpoint". In fact, it is (more or less) exactly as big as the Admin API, as it includes all the messages that could come back. So we left the problem for all controller developers.

That said, I'm not a developer and so I don't know exactly what tooling is needed. Is it worth the effort of maintaining and ensuring the accuracy of a webhooks OpenAPI spec for the contoller developer? Is there an approach that would allow us to ensure it stayed accurate?

ianco commented 2 years ago

Just revisiting this issue - I think we need to provide an openapi spec for what a webhook server needs to implement, or at least update the docs for what a webhook recipient should expect to receive.

Right now the process involved setting up the webhook listener, triggering the webhook, and then inspecting the message that is received. Not ideal :-(