From 74243a8cae36099a5806ccf76422c1d2304eab21 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 09:32:34 +0000 Subject: [PATCH 1/9] WIP: update docs, include new OpenAPI --- CMakeLists.txt | 2 +- doc/build_apps/run_app.rst | 2 +- doc/governance/accept_recovery.rst | 20 +- .../gov_api_schemas/2023-06-01-preview.rst | 8 + doc/governance/gov_api_schemas/classic.rst | 9 + doc/governance/member_rpc_api.rst | 10 +- .../examples/Ballots_Get.json | 16 + .../examples/Ballots_Submit.json | 24 + .../examples/EncryptedShares_Get.json | 15 + .../examples/Proposals_Create.json | 19 + .../examples/Proposals_Get.json | 22 + .../examples/Proposals_GetActions.json | 23 + .../examples/Proposals_List.json | 26 + .../examples/Proposals_Withdraw.json | 23 + .../ServiceState_GetConstitution.json | 14 + .../ServiceState_GetJoinPolicies.json | 29 + .../examples/ServiceState_GetJsApp.json | 27 + .../examples/ServiceState_GetJwkInfo.json | 23 + .../examples/ServiceState_GetMember.json | 17 + .../examples/ServiceState_GetNode.json | 29 + .../examples/ServiceState_GetServiceInfo.json | 22 + .../examples/ServiceState_ListMembers.json | 31 + .../examples/ServiceState_ListNodes.json | 50 + .../examples/Shares_Submit.json | 18 + .../examples/StateDigests_Acknowledge.json | 12 + .../examples/StateDigests_Get.json | 15 + .../examples/StateDigests_Update.json | 16 + .../examples/Transactions_Get.json | 15 + .../examples/Transactions_GetCommit.json | 15 + .../mccf/2023-06-01-preview/mccfgov.json | 2258 +++++++++++++++++ doc/use_apps/issue_commands.rst | 4 +- js/ccf-app/package.json | 4 +- scripts/ci-checks.sh | 4 +- src/node/gov/2023-06-01-preview.json | 1 - 34 files changed, 2801 insertions(+), 22 deletions(-) create mode 100644 doc/governance/gov_api_schemas/2023-06-01-preview.rst create mode 100644 doc/governance/gov_api_schemas/classic.rst create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Get.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Submit.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/EncryptedShares_Get.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Create.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Get.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Proposals_GetActions.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Proposals_List.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Withdraw.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetConstitution.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJoinPolicies.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJsApp.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJwkInfo.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetMember.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetNode.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetServiceInfo.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListMembers.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListNodes.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Shares_Submit.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Acknowledge.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Get.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Update.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Transactions_Get.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/examples/Transactions_GetCommit.json create mode 100644 doc/schemas/mccf/2023-06-01-preview/mccfgov.json delete mode 100644 src/node/gov/2023-06-01-preview.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 22992f340304..5fa677b3e42e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,7 +652,7 @@ configure_file( @ONLY ) -file(READ ${CCF_DIR}/src/node/gov/2023-06-01-preview.json +file(READ ${CCF_DIR}/doc/schemas/mccf/2023-06-01-preview/mccfgov.json GOV_API_SCHEMA_2023_06_01_PREVIEW ) configure_file( diff --git a/doc/build_apps/run_app.rst b/doc/build_apps/run_app.rst index 40f63a184178..7477035fd1ae 100644 --- a/doc/build_apps/run_app.rst +++ b/doc/build_apps/run_app.rst @@ -91,7 +91,7 @@ This should look much like a standard HTTP server, with error codes for missing $ curl https://127.0.0.1:8000/app/not/a/real/resource -X GET --cacert service_cert.pem --cert user0_cert.pem --key user0_privk.pem -i HTTP/1.1 404 Not Found - $ curl https://127.0.0.1:8000/gov/proposals -X POST --cacert service_cert.pem --cert user0_cert.pem --key user0_privk.pem -i + $ curl https://127.0.0.1:8000/gov/members/proposals:create?api-version=2023-06-01-preview -X POST --cacert service_cert.pem --cert user0_cert.pem --key user0_privk.pem -i HTTP/1.1 403 Forbidden Logging App Commands diff --git a/doc/governance/accept_recovery.rst b/doc/governance/accept_recovery.rst index 77167925c049..689b560cce2b 100644 --- a/doc/governance/accept_recovery.rst +++ b/doc/governance/accept_recovery.rst @@ -28,7 +28,7 @@ A member proposes to recover the network and other members can vote on the propo .. code-block:: bash $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member1_privk.pem --signing-cert member1_cert.pem --content transition_service_to_open.json | \ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + curl https:///gov/members/proposals:create?api-version=2023-06-01-preview --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" { "ballot_count": 0, "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", @@ -37,7 +37,7 @@ A member proposes to recover the network and other members can vote on the propo } $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 --signing-key member1_privk.pem --signing-cert member1_cert.pem --content vote_accept.json | \ - curl https:///gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + curl https:///gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1:submit?api-version=2023-06-01-preview --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" { "ballot_count": 1, "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", @@ -46,7 +46,7 @@ A member proposes to recover the network and other members can vote on the propo } $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 --signing-key member2_privk.pem --signing-cert member2_cert.pem --content vote_accept.json | \ - curl https:///gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + curl https:///gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/e306e3a6eead2f4a3854302b41c3015bf12db9535ac0be1b8cf6584f84bca92b:submit?api-version=2023-06-01-preview --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" { "ballot_count": 2, "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", @@ -67,20 +67,20 @@ To restore private transactions and complete the recovery procedure, recovery me .. note:: The recovery members who submit their recovery shares do not necessarily have to be the members who previously accepted the recovery. -Member recovery shares are stored in the ledger, encrypted with each member's public encryption key. Members can retrieve their encrypted recovery shares from the public-only service via the :http:GET:`/gov/encrypted_recovery_share/{member_id}` endpoint, perform the share decryption securely (see for example :doc:`hsm_keys`) and submit the decrypted recovery share via the :http:POST:`/gov/recovery_share` endpoint. +Member recovery shares are stored in the ledger, encrypted with each member's public encryption key. Members can retrieve their encrypted recovery shares from the public-only service via the :http:GET:`/gov/recovery/encrypted-shares/{memberId}` endpoint, perform the share decryption securely (see for example :doc:`hsm_keys`) and submit the decrypted recovery share via the :http:POST:`/gov/recovery/members/{memberId}:recover` endpoint. The recovery share retrieval, decryption and submission steps can be conveniently performed in one step using the ``submit_recovery_share.sh`` script: .. code-block:: bash - $ submit_recovery_share.sh https:// --member-enc-privk member0_enc_privk.pem --cert member0_cert.pem + $ submit_recovery_share.sh https:// --member-enc-privk member0_enc_privk.pem --cert member0_cert.pem --api-version 2023-06-01-preview --key member0_privk.pem --cacert service_cert.pem HTTP/1.1 200 OK content-type: text/plain x-ms-ccf-transaction-id: 4.28 1/2 recovery shares successfully submitted. - $ submit_recovery_share.sh https:// --member-enc-privk member1_enc_privk.pem --cert member1_cert.pem + $ submit_recovery_share.sh https:// --member-enc-privk member1_enc_privk.pem --cert member1_cert.pem --api-version 2023-06-01-preview --key member1_privk.pem --cacert service_cert.pem HTTP/1.1 200 OK content-type: text/plain @@ -115,16 +115,16 @@ Summary Diagram Node 2-->>Member 1: State: Accepted Note over Node 2, Node 3: transition_service_to_open proposal completes.
Service is ready to accept recovery shares. - Member 0->>+Node 2: GET /gov/encrypted_recovery_share/ + Member 0->>+Node 2: GET /gov/recovery/encrypted-shares/ Node 2-->>Member 0: Encrypted recovery share for Member 0 Note over Member 0: Decrypts recovery share - Member 0->>+Node 2: POST /gov/recovery_share: "" + Member 0->>+Node 2: POST /gov/recovery/members/:recover": "" Node 2-->>Member 0: 1/2 recovery shares successfully submitted. - Member 1->>+Node 2: GET /gov/encrypted_recovery_share/ + Member 1->>+Node 2: GET /gov/recovery/encrypted-shares/ Node 2-->>Member 1: Encrypted recovery share for Member 1 Note over Member 1: Decrypts recovery share - Member 1->>+Node 2: POST /gov/recovery_share: "" + Member 1->>+Node 2: POST /gov/recovery/members/:recover": "" Node 2-->>Member 1: End of recovery procedure initiated. Note over Node 2, Node 3: Reading Private Ledger... diff --git a/doc/governance/gov_api_schemas/2023-06-01-preview.rst b/doc/governance/gov_api_schemas/2023-06-01-preview.rst new file mode 100644 index 000000000000..34cccca1ee46 --- /dev/null +++ b/doc/governance/gov_api_schemas/2023-06-01-preview.rst @@ -0,0 +1,8 @@ +2023-06-01-preview +================== + +This API is available by passing the query parameter ``api-version=2023-06-01-preview`` to endpoints under the ``/gov`` prefix. + +This is available from CCF 5.0.0. + +.. openapi:: ../../schemas/mccf/2023-06-01-preview/mccfgov.json \ No newline at end of file diff --git a/doc/governance/gov_api_schemas/classic.rst b/doc/governance/gov_api_schemas/classic.rst new file mode 100644 index 000000000000..1df19b8fd8f6 --- /dev/null +++ b/doc/governance/gov_api_schemas/classic.rst @@ -0,0 +1,9 @@ +Classic API +=========== + +Available in CCF versions before v5.0.0. + +.. warning:: This API is deprecated, and will be removed in a future release. Use a more recent version. + +.. openapi:: ../../schemas/gov_openapi.json + :examples: \ No newline at end of file diff --git a/doc/governance/member_rpc_api.rst b/doc/governance/member_rpc_api.rst index 9c287864e7b8..2e8a410b57b4 100644 --- a/doc/governance/member_rpc_api.rst +++ b/doc/governance/member_rpc_api.rst @@ -1,7 +1,11 @@ Member RPC API ============== -Member RPCs are exposed under ``/gov`` and require authentication with a valid member identity. +Member RPCs are exposed under ``/gov``. Many require COSE authentication, with the payload signed by a member identity. Others provide public read access to governance state. -.. openapi:: ../schemas/gov_openapi.json - :examples: \ No newline at end of file +# TODO: The following is the old, deprecated API + +.. toctree:: + + gov_api_schemas/2023-06-01-preview + gov_api_schemas/classic diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Get.json b/doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Get.json new file mode 100644 index 000000000000..5efafd2b1bfa --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Get.json @@ -0,0 +1,16 @@ +{ + "title": "Ballots_Get", + "operationId": "Ballots_Get", + "parameters": { + "api-version": "2023-06-01-preview", + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970" + }, + "responses": { + "200": { + "body": { + "script": "export function vote (rawProposal, proposerId) { return true }" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Submit.json b/doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Submit.json new file mode 100644 index 000000000000..338d6a9101db --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Ballots_Submit.json @@ -0,0 +1,24 @@ +{ + "title": "Ballots_Submit", + "operationId": "Ballots_Submit", + "parameters": { + "api-version": "2023-06-01-preview", + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "body": "{binary COSE Sign1}" + }, + "responses": { + "200": { + "body": { + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "proposalState": "Open", + "ballotCount": 2, + "finalVotes": { + "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true, + "b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/EncryptedShares_Get.json b/doc/schemas/mccf/2023-06-01-preview/examples/EncryptedShares_Get.json new file mode 100644 index 000000000000..e3ecf63fe9d3 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/EncryptedShares_Get.json @@ -0,0 +1,15 @@ +{ + "title": "EncryptedShares_Get", + "operationId": "EncryptedShares_Get", + "parameters": { + "api-version": "2023-06-01-preview", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970" + }, + "responses": { + "200": { + "body": { + "encryptedShare": "ZW5jcnlwdGVkU2hhcmUx" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Create.json b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Create.json new file mode 100644 index 000000000000..75db66510eee --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Create.json @@ -0,0 +1,19 @@ +{ + "title": "Proposals_Create", + "operationId": "Proposals_Create", + "parameters": { + "api-version": "2023-06-01-preview", + "body": "{binary COSE Sign1}" + }, + "responses": { + "200": { + "body": { + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "proposalState": "Open", + "ballotCount": 0, + "finalVotes": {} + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Get.json b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Get.json new file mode 100644 index 000000000000..8393fcc103ac --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Get.json @@ -0,0 +1,22 @@ +{ + "title": "Proposals_Get", + "operationId": "Proposals_Get", + "parameters": { + "api-version": "2023-06-01-preview", + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b" + }, + "responses": { + "200": { + "body": { + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "proposalState": "Open", + "ballotCount": 2, + "finalVotes": { + "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true, + "b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_GetActions.json b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_GetActions.json new file mode 100644 index 000000000000..34b473f2cc6e --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_GetActions.json @@ -0,0 +1,23 @@ +{ + "title": "Proposals_GetActions", + "operationId": "Proposals_GetActions", + "parameters": { + "api-version": "2023-06-01-preview", + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b" + }, + "responses": { + "200": { + "body": { + "actions": [ + { + "name": "set_member", + "args": { + "cert": "-----BEGIN CERTIFICATE-----\nMIIBtzCCATygAwIBAgIUYqXLFcT1aCENVpgp2K+Vv53cauEwCgYIKoZIzj0EAwMw\nEjEQMA4GA1UEAwwHbWVtYmVyMzAeFw0yMzA1MTcxMzUwMzJaFw0yNDA1MTYxMzUw\nMzJaMBIxEDAOBgNVBAMMB21lbWJlcjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQI\ngWV8Lcf+eegGXVj1I4N8jWcfTb6MRt0Znl8aFOBBwZ5lgRlTePYLHBb81wOJaX+k\nIYqHRaI3Wblg72gV/dhf4qBYw9ENqJtE2ClenYkRFAX2/1GwjxTOf9XGpBUt5Rij\nUzBRMB0GA1UdDgQWBBT7oAebRrqSDSG89jW0nFF5fHRRTzAfBgNVHSMEGDAWgBT7\noAebRrqSDSG89jW0nFF5fHRRTzAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMD\nA2kAMGYCMQCmCKWLEbCooecDiuMyUf/B2vppNZ75U96B2ypg88Xy5y4xhRV1qoCT\nRT4sUCFl6ioCMQCKm0df2DzlRbhX6+0i6KikBkUf9kFowb5ctikJsym0rTigpPZC\nHaZlaQD2pNBud/0=\n-----END CERTIFICATE-----\n", + "encryption_pub_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzIh4oWoiTFCu/8tsfmo9\njTDryaTrL7wo8+HJAGUTL827CiZ8Rm9wgo7iJDOza7UPaPnXpR6kIlZbdItDOx9k\nmJSVWbDMufaqqs+y/i+WrTiDqL02zbT/lI4kx5l7Wyu0VEHT5GmSKQiVyJt/Q4vE\n1b9rKNy3Ol1g5VuW9PKOHFz3tvjWksVWXi16qulN3IjAhSFVRtasbqdNSNdDbirv\nLTe24Y9v7UP8CI3qgjr3x8qLYM/X0ou4ZcJvXWVtxZfQLGVgyZcgHD6OtbYJr9Iy\neh/x+G3pPFg2eQY8xNZgqqtH1StKcI++eD7iSDosKRkN3efCKLeKStg6F/xluarc\nkQIDAQAB\n-----END PUBLIC KEY-----\n" + } + } + ] + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_List.json b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_List.json new file mode 100644 index 000000000000..31ac4c031845 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_List.json @@ -0,0 +1,26 @@ +{ + "title": "Proposals_List", + "operationId": "Proposals_List", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "proposalState": "Open", + "ballotCount": 2, + "finalVotes": { + "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true, + "b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false + } + } + ], + "nextLink": "https://microsoft.com/avwpnzmy" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Withdraw.json b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Withdraw.json new file mode 100644 index 000000000000..4fdcbbb28f44 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Proposals_Withdraw.json @@ -0,0 +1,23 @@ +{ + "title": "Proposals_Withdraw", + "operationId": "Proposals_Withdraw", + "parameters": { + "api-version": "2023-06-01-preview", + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "body": "{binary COSE Sign1}" + }, + "responses": { + "200": { + "body": { + "proposalId": "1c04c5bb4bdc207dbf35bc4b32dbf92cbc23eabb34a6e8b163b2de2c7833e87b", + "proposerId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "proposalState": "Withdrawn", + "ballotCount": 2, + "finalVotes": { + "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970": true, + "b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7": false + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetConstitution.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetConstitution.json new file mode 100644 index 000000000000..a1fed267bb97 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetConstitution.json @@ -0,0 +1,14 @@ +{ + "title": "ServiceState_GetConstitution", + "operationId": "ServiceState_GetConstitution", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "constitution": "export function validate(input) {\n ...\n}\n\nexport function resolve(proposal, proposerId, votes) {\n ...\n}\n\nexport function apply(proposal, proposalId) {\n ...\n}\n" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJoinPolicies.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJoinPolicies.json new file mode 100644 index 000000000000..632d290bae7f --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJoinPolicies.json @@ -0,0 +1,29 @@ +{ + "title": "ServiceState_GetJoinPolicies", + "operationId": "ServiceState_GetJoinPolicies", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "sgx": { + "measurements": [ + "cs/RoNCp2UCxpN+i1UnVYw==" + ] + }, + "snp": { + "measurements": [ + "XqJZLOA9/xCx9nnsDch4vw==" + ], + "hostData": { + "key9497": "NiNrjmA9/aSj4F076mVdrA==" + }, + "uvmEndorsements": { + "key9553": "cbneXARxfLGcqw3cc09mYQ==" + } + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJsApp.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJsApp.json new file mode 100644 index 000000000000..ab9db2363d6a --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJsApp.json @@ -0,0 +1,27 @@ +{ + "title": "ServiceState_GetJsApp", + "operationId": "ServiceState_GetJsApp", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "endpoints": { + "/compute": { + "post": { + "jsModule": "math.js", + "jsFunction": "compute", + "forwardingRequired": "Sometimes", + "authnPolicies": [ + "user_cert" + ], + "mode": "ReadOnly", + "openApi": {} + } + } + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJwkInfo.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJwkInfo.json new file mode 100644 index 000000000000..86aa125d9392 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetJwkInfo.json @@ -0,0 +1,23 @@ +{ + "title": "ServiceState_GetJwkInfo", + "operationId": "ServiceState_GetJwkInfo", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "issuers": { + "idprovider.myservice.example.com": { + "keyFilter": "All", + "autoRefresh": true, + "caCertBundleName": "MyIdProviderCa" + } + }, + "caCertBundles": { + "MyIdProviderCa": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n" + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetMember.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetMember.json new file mode 100644 index 000000000000..8afa37ceb960 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetMember.json @@ -0,0 +1,17 @@ +{ + "title": "ServiceState_GetMember", + "operationId": "ServiceState_GetMember", + "parameters": { + "api-version": "2023-06-01-preview", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970" + }, + "responses": { + "200": { + "body": { + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "status": "Accepted", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIBtjCCATygAwIBAgIUQReVbbmYi3jwIKLajvRSSazrlHgwCgYIKoZIzj0EAwMw\nEjEQMA4GA1UEAwwHbWVtYmVyMDAeFw0yMzA1MTcxMzUwMzBaFw0yNDA1MTYxMzUw\nMzBaMBIxEDAOBgNVBAMMB21lbWJlcjAwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQL\nHTNizYCCd+qvH5hMkikWRRb9s3cmD1PIkeoqRIqJ98FF2PgW/cPhM8wyJ3KK8tqS\n7MI6rW8AFgRf2CV3nJ3uNwVrbdgbmmGef8WTyFBXX3VvypntT+jCHDg9HURROAmj\nUzBRMB0GA1UdDgQWBBSljyQ0GfGDm8ODrpcWy364SPRUHjAfBgNVHSMEGDAWgBSl\njyQ0GfGDm8ODrpcWy364SPRUHjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMD\nA2gAMGUCMDUoePU2bJxAt9lXDX0TCQrt1xMBZc5BNvVi2ROEQEKHSetVgzAADzFC\n/8Te+S/+kwIxAJMFEeGSbXaUNxvQLHJehaORV0Bw2FJN+zkb3FAltwlua+REfl/t\nPcn7nq5mpQ0RNQ==\n-----END CERTIFICATE-----\n" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetNode.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetNode.json new file mode 100644 index 000000000000..8be95c14d702 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetNode.json @@ -0,0 +1,29 @@ +{ + "title": "ServiceState_GetNode", + "operationId": "ServiceState_GetNode", + "parameters": { + "api-version": "2023-06-01-preview", + "nodeId": "7e87b5de68f7edb26d2c31b69eda2cb3fac6ec125fdaafecdbe184abc5f61573" + }, + "responses": { + "200": { + "body": { + "nodeId": "7e87b5de68f7edb26d2c31b69eda2cb3fac6ec125fdaafecdbe184abc5f61573", + "status": "Trusted", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIByDCCAU6gAwIBAgIQBU64KAw8A7HsEUJCvArBWDAKBggqhkjOPQQDAzATMREw\nDwYDVQQDDAhDQ0YgTm9kZTAeFw0yMzA1MTcxMzUwMzBaFw0yMzA1MTgxMzUwMjla\nMBMxETAPBgNVBAMMCENDRiBOb2RlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEqo97\nwuOBeYkmXGcDXAuGSQfDbTplLGyvls42TcwntLN/GkHxj6pe0l6h7BC0VV828J5/\na21q6sATQsXyFpZxIxIB6R/5s2blslk6INVuq03qkGz8hmGrpI/MJh//89Wjo2cw\nZTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBR7QYSt32ibJwNKLAbfdeMu\nuyy6uDAfBgNVHSMEGDAWgBR7QYSt32ibJwNKLAbfdeMuuyy6uDAPBgNVHREECDAG\nhwR/yGnoMAoGCCqGSM49BAMDA2gAMGUCMBS9Hhd4mHjPjJ16n1L6KBshAzlT1IAA\n4jiVaTXqc6shnvfoHljw54jCVm/KpKAzRQIxANS8KrmXhW3cr4rkYWHipJEXzMJe\n8ZL6xWgCY6Fb63JNEYpQP+W3HZqaqKJrdvgTyw==\n-----END CERTIFICATE-----\n", + "retiredCommitted": false, + "quoteInfo": { + "format": "OE_SGX_v1", + "quote": "iqCn2D8gcLapGOmaS/wFlg==", + "endorsements": "xIuY7WOg/FR7/tlqDAWcxQ==" + }, + "rpcInterfaces": { + "publicHttps": { + "publishedAddress": "ccf.dev:12345", + "protocol": "HTTP1" + } + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetServiceInfo.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetServiceInfo.json new file mode 100644 index 000000000000..ace18ff30e5c --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_GetServiceInfo.json @@ -0,0 +1,22 @@ +{ + "title": "ServiceState_GetServiceInfo", + "operationId": "ServiceState_GetServiceInfo", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "status": "Open", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIBvjCCAUSgAwIBAgIRAKMpqEu0tXPD9gmJTV/RDdcwCgYIKoZIzj0EAwMwFjEU\nMBIGA1UEAwwLQ0NGIE5ldHdvcmswHhcNMjMwNTE2MTUxNzIyWhcNMjMwNTE3MTUx\nNzIxWjAWMRQwEgYDVQQDDAtDQ0YgTmV0d29yazB2MBAGByqGSM49AgEGBSuBBAAi\nA2IABKGiSg+X2EofhkL9rmpnvRAsRDMRW1cErnYA7gv3Y1s+g0srVPG5Fh85I2GO\nxVgj/hICXsR/bPPjDW3NLJ7gvzbtU4XnLsixkRPa9mkWM9GePaimUNs6NnbWI/5/\ndZkkSqNWMFQwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUglDhOi9RqGAj\nwT2EFycWlLeZnrIwHwYDVR0jBBgwFoAUglDhOi9RqGAjwT2EFycWlLeZnrIwCgYI\nKoZIzj0EAwMDaAAwZQIwR6PFt+sC1nbFGskq8D+o8dBPihhZGxrthRIUtROYFTWU\ncfw59zRFYGffJH0qXV3tAjEAzldbGZNiFL6sTEmv+lfKdeSfZphZmVQttJ0yQ+l8\nM4qqgkU90BWODS/7RIDFMB73\n-----END CERTIFICATE-----\n", + "recoveryCount": 1, + "creationTransactionId": "7.1672", + "previousServiceCreationTransactionId": "2.1", + "configuration": { + "maximumNodeCertificateValidityDays": 180, + "recentCoseProposalsWindowSize": 100 + } + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListMembers.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListMembers.json new file mode 100644 index 000000000000..b9495272ceac --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListMembers.json @@ -0,0 +1,31 @@ +{ + "title": "ServiceState_ListMembers", + "operationId": "ServiceState_ListMembers", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "status": "Accepted", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIBtjCCATygAwIBAgIUQReVbbmYi3jwIKLajvRSSazrlHgwCgYIKoZIzj0EAwMw\nEjEQMA4GA1UEAwwHbWVtYmVyMDAeFw0yMzA1MTcxMzUwMzBaFw0yNDA1MTYxMzUw\nMzBaMBIxEDAOBgNVBAMMB21lbWJlcjAwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQL\nHTNizYCCd+qvH5hMkikWRRb9s3cmD1PIkeoqRIqJ98FF2PgW/cPhM8wyJ3KK8tqS\n7MI6rW8AFgRf2CV3nJ3uNwVrbdgbmmGef8WTyFBXX3VvypntT+jCHDg9HURROAmj\nUzBRMB0GA1UdDgQWBBSljyQ0GfGDm8ODrpcWy364SPRUHjAfBgNVHSMEGDAWgBSl\njyQ0GfGDm8ODrpcWy364SPRUHjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMD\nA2gAMGUCMDUoePU2bJxAt9lXDX0TCQrt1xMBZc5BNvVi2ROEQEKHSetVgzAADzFC\n/8Te+S/+kwIxAJMFEeGSbXaUNxvQLHJehaORV0Bw2FJN+zkb3FAltwlua+REfl/t\nPcn7nq5mpQ0RNQ==\n-----END CERTIFICATE-----\n" + }, + { + "memberId": "b9626e3856b3ef3b433e612d59fbb9edd71cfa2efc772bcfbb50aaa9b6e033f7", + "status": "Accepted", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIBtTCCATygAwIBAgIUbMeV2BFlZO11PM0FoiuJjmLVSiIwCgYIKoZIzj0EAwMw\nEjEQMA4GA1UEAwwHbWVtYmVyMTAeFw0yMzA1MTcxMzUwMzBaFw0yNDA1MTYxMzUw\nMzBaMBIxEDAOBgNVBAMMB21lbWJlcjEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR3\nGPE7tBnEj5MwMMO6y376VQLfPFCVI9+LI4Ndc1ieLRIii+oydrwzthxv10juy+Nl\nSoD67n1y6ehbMB9JKEGMnkBfuZNKuXAqb2h371y2d/jrX/pZmyy3AIICnKYTQ7Oj\nUzBRMB0GA1UdDgQWBBQf2ImVBp4MWgpLz6OlOUY65VGbRTAfBgNVHSMEGDAWgBQf\n2ImVBp4MWgpLz6OlOUY65VGbRTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMD\nA2cAMGQCMDCW/sHEGuxowkv1x1q+/8cRO9YAa3HxASkqz9/MK2r+jyOFawKtaRpc\n7QwvBOkLFwIwEK6Q9aCTrjGkoxITnFmIc+nnv+wh4xRkUNam/nQebMRQSHI9TUXN\n8sQwxjb50U7L\n-----END CERTIFICATE-----\n" + }, + { + "memberId": "ecf07a6c69266e14cedea8cfc0049c04201501f5c7ea5cf7180ad56efbd84714", + "status": "Accepted", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIBtjCCATygAwIBAgIUbpzHWRHXRoDOjyqYlFk7itQ5qWgwCgYIKoZIzj0EAwMw\nEjEQMA4GA1UEAwwHbWVtYmVyMjAeFw0yMzA1MTcxMzUwMzBaFw0yNDA1MTYxMzUw\nMzBaMBIxEDAOBgNVBAMMB21lbWJlcjIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASA\n4495qU2huzUZHWCf/ovT+C28AlDIaGejvc9qxaRKJ+dXAdZ10C6Z3TMXYGKlpE2K\nCz/VyOMsdwBiN8rJs4L1bLWRh3vZnyoVyp3quq34wc90UINv3lNK8XnxcONtkaGj\nUzBRMB0GA1UdDgQWBBQeZ+IKLpQ4nd3CSxxaj+8X+eV+TTAfBgNVHSMEGDAWgBQe\nZ+IKLpQ4nd3CSxxaj+8X+eV+TTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMD\nA2gAMGUCMGWloVqJ7mvY7bFp5vfSPICnpMUL6sat62Ag/2ZZ1FRqWTXokuqRH2UI\nOJyLpI245QIxAKXY58sTZIVzlXkYGp0z3TrTkVQ/pipWD7MpNzr1+7afQWj1Dw+r\npznvF6OHoz0fTA==\n-----END CERTIFICATE-----\n" + } + ], + "nextLink": "https://microsoft.com/ak" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListNodes.json b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListNodes.json new file mode 100644 index 000000000000..e844e179e608 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/ServiceState_ListNodes.json @@ -0,0 +1,50 @@ +{ + "title": "ServiceState_ListNodes", + "operationId": "ServiceState_ListNodes", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "nodeId": "7e87b5de68f7edb26d2c31b69eda2cb3fac6ec125fdaafecdbe184abc5f61573", + "status": "Trusted", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIByDCCAU6gAwIBAgIQBU64KAw8A7HsEUJCvArBWDAKBggqhkjOPQQDAzATMREw\nDwYDVQQDDAhDQ0YgTm9kZTAeFw0yMzA1MTcxMzUwMzBaFw0yMzA1MTgxMzUwMjla\nMBMxETAPBgNVBAMMCENDRiBOb2RlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEqo97\nwuOBeYkmXGcDXAuGSQfDbTplLGyvls42TcwntLN/GkHxj6pe0l6h7BC0VV828J5/\na21q6sATQsXyFpZxIxIB6R/5s2blslk6INVuq03qkGz8hmGrpI/MJh//89Wjo2cw\nZTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBR7QYSt32ibJwNKLAbfdeMu\nuyy6uDAfBgNVHSMEGDAWgBR7QYSt32ibJwNKLAbfdeMuuyy6uDAPBgNVHREECDAG\nhwR/yGnoMAoGCCqGSM49BAMDA2gAMGUCMBS9Hhd4mHjPjJ16n1L6KBshAzlT1IAA\n4jiVaTXqc6shnvfoHljw54jCVm/KpKAzRQIxANS8KrmXhW3cr4rkYWHipJEXzMJe\n8ZL6xWgCY6Fb63JNEYpQP+W3HZqaqKJrdvgTyw==\n-----END CERTIFICATE-----\n", + "retiredCommitted": false, + "quoteInfo": { + "format": "OE_SGX_v1", + "quote": "iqCn2D8gcLapGOmaS/wFlg==", + "endorsements": "xIuY7WOg/FR7/tlqDAWcxQ==" + }, + "rpcInterfaces": { + "publicHttps": { + "publishedAddress": "ccf.dev:12345", + "protocol": "HTTP1" + } + } + }, + { + "nodeId": "5bc78bd280bbd86387bbc448b5b7defbc2ecded715537b3aa742ceae35ab4302", + "status": "Retired", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIByDCCAU6gAwIBAgIQOBe5SrcwReWmSzTjzj2HDjAKBggqhkjOPQQDAzATMREw\nDwYDVQQDDAhDQ0YgTm9kZTAeFw0yMzA1MTcxMzUwMzFaFw0yMzA1MTgxMzUwMzBa\nMBMxETAPBgNVBAMMCENDRiBOb2RlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE74qL\nAc/45tiriN5MuquYhHVdMGQRvYSm08HBfYcODtET88qC0A39o6Y2TmfbIn6BdjMG\nkD58o377ZMTaApQu/oJcwt7qZ9/LE8j8WU2qHn0cPTlpwH/2tiud2w+U3voSo2cw\nZTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS9FJNwWSXtUpHaBV57EwTW\noM8vHjAfBgNVHSMEGDAWgBS9FJNwWSXtUpHaBV57EwTWoM8vHjAPBgNVHREECDAG\nhwR/xF96MAoGCCqGSM49BAMDA2gAMGUCMQDKxpjPToJ7VSqKqQSeMuW9tr4iL+9I\n7gTGdGwiIYV1qTSS35Sk9XQZ0VpSa58c/5UCMEgmH71k7XlTGVUypm4jAgjpC46H\ns+hJpGMvyD9dKzEpZgmZYtghbyakUkwBiqmFQA==\n-----END CERTIFICATE-----\n", + "retiredCommitted": true, + "quoteInfo": { + "format": "OE_SGX_v1", + "quote": "4n3t9RVQZomjwsAZyiyAuQ==", + "endorsements": "lvpmei0YwtfvVa4RaK8n+g==" + }, + "rpcInterfaces": { + "publicHttps": { + "publishedAddress": "ccf.dev:12345", + "protocol": "HTTP1" + } + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Shares_Submit.json b/doc/schemas/mccf/2023-06-01-preview/examples/Shares_Submit.json new file mode 100644 index 000000000000..a95b77147406 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Shares_Submit.json @@ -0,0 +1,18 @@ +{ + "title": "Shares_Submit", + "operationId": "Shares_Submit", + "parameters": { + "api-version": "2023-06-01-preview", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "body": "{binary COSE Sign1}" + }, + "responses": { + "200": { + "body": { + "message": "3/3 recovery shares successfully submitted.", + "submittedCount": 0, + "recoveryThreshold": 0 + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Acknowledge.json b/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Acknowledge.json new file mode 100644 index 000000000000..185d6922177c --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Acknowledge.json @@ -0,0 +1,12 @@ +{ + "title": "StateDigests_Acknowledge", + "operationId": "StateDigests_Acknowledge", + "parameters": { + "api-version": "2023-06-01-preview", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "body": "{binary COSE Sign1}" + }, + "responses": { + "204": {} + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Get.json b/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Get.json new file mode 100644 index 000000000000..cdc871bbe825 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Get.json @@ -0,0 +1,15 @@ +{ + "title": "StateDigests_Get", + "operationId": "StateDigests_Get", + "parameters": { + "api-version": "2023-06-01-preview", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970" + }, + "responses": { + "200": { + "body": { + "digest": "1cdc59855bb6b7edee42769ca3767bc9684b7a62ffcfcb8751a75dbe71c28e49" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Update.json b/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Update.json new file mode 100644 index 000000000000..d7c807f2f364 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/StateDigests_Update.json @@ -0,0 +1,16 @@ +{ + "title": "StateDigests_Update", + "operationId": "StateDigests_Update", + "parameters": { + "api-version": "2023-06-01-preview", + "memberId": "f8ac7c60c164f7f13c04ba41645b18eabcc55a8f799c83a90d001f4e89907970", + "body": "{binary COSE Sign1}" + }, + "responses": { + "200": { + "body": { + "digest": "1cdc59855bb6b7edee42769ca3767bc9684b7a62ffcfcb8751a75dbe71c28e49" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Transactions_Get.json b/doc/schemas/mccf/2023-06-01-preview/examples/Transactions_Get.json new file mode 100644 index 000000000000..3148b8e31175 --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Transactions_Get.json @@ -0,0 +1,15 @@ +{ + "title": "Transactions_Get", + "operationId": "Transactions_Get", + "parameters": { + "api-version": "2023-06-01-preview", + "transactionId": "2.42" + }, + "responses": { + "200": { + "body": { + "status": "Committed" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/examples/Transactions_GetCommit.json b/doc/schemas/mccf/2023-06-01-preview/examples/Transactions_GetCommit.json new file mode 100644 index 000000000000..babdb7b5a43a --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/examples/Transactions_GetCommit.json @@ -0,0 +1,15 @@ +{ + "title": "Transactions_GetCommit", + "operationId": "Transactions_GetCommit", + "parameters": { + "api-version": "2023-06-01-preview" + }, + "responses": { + "200": { + "body": { + "status": "Committed", + "transactionId": "7.2385" + } + } + } +} diff --git a/doc/schemas/mccf/2023-06-01-preview/mccfgov.json b/doc/schemas/mccf/2023-06-01-preview/mccfgov.json new file mode 100644 index 000000000000..cafabab8cd9d --- /dev/null +++ b/doc/schemas/mccf/2023-06-01-preview/mccfgov.json @@ -0,0 +1,2258 @@ +{ + "swagger": "2.0", + "info": { + "title": "Managed CCF Governance", + "version": "2023-06-01-preview", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "tags": [], + "paths": { + "/gov/members/proposals": { + "get": { + "operationId": "Proposals_List", + "description": "Returns all current proposed changes to the service. Note that non-open proposals (ie - those which have already been accepted, rejected, withdrawn, etc) are not returned.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/PagedProposal" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Proposals_List": { + "$ref": "./examples/Proposals_List.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/gov/members/proposals/{proposalId}:withdraw": { + "post": { + "operationId": "Proposals_Withdraw", + "description": "Withdraw an existing proposal. Only the original proposer is permitted to withdraw.", + "consumes": [ + "application/cose" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "proposalId", + "in": "path", + "description": "Unique ID assigned to this proposal at its submission, by the service.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "$ref": "#/parameters/CoseSignature.body" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Proposals.Proposal" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Proposals_Withdraw": { + "$ref": "./examples/Proposals_Withdraw.json" + } + } + } + }, + "/gov/members/proposals/{proposalId}": { + "get": { + "operationId": "Proposals_Get", + "description": "Returns a summary of a single proposed change to the service.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "proposalId", + "in": "path", + "description": "Unique ID assigned to this proposal at its submission, by the service.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Proposals.Proposal" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Proposals_Get": { + "$ref": "./examples/Proposals_Get.json" + } + } + } + }, + "/gov/members/proposals/{proposalId}/actions": { + "get": { + "operationId": "Proposals_GetActions", + "description": "Returns actions contained in a proposal.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "proposalId", + "in": "path", + "description": "Unique ID assigned to this proposal at its submission, by the service.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Proposals.ProposalActions" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Proposals_GetActions": { + "$ref": "./examples/Proposals_GetActions.json" + } + } + } + }, + "/gov/members/proposals/{proposalId}/ballots/{memberId}:submit": { + "post": { + "operationId": "Ballots_Submit", + "description": "Submit an executable ballot for a specific proposal. This may be as simple as `return true` to vote in favour, or contain reads from the KV and conditions on the proposal contents.", + "consumes": [ + "application/cose" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "proposalId", + "in": "path", + "description": "Unique ID assigned to this proposal at its submission, by the service.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "name": "memberId", + "in": "path", + "description": "ID of CCF member who signed and submitted this ballot.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "$ref": "#/parameters/CoseSignature.body" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Proposals.Proposal" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Ballots_Submit": { + "$ref": "./examples/Ballots_Submit.json" + } + } + } + }, + "/gov/members/proposals/{proposalId}/ballots/{memberId}": { + "get": { + "operationId": "Ballots_Get", + "description": "Returns a member's submitted ballot.", + "produces": [ + "text/javascript", + "application/json" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "proposalId", + "in": "path", + "description": "Unique ID assigned to this proposal at its submission, by the service.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "name": "memberId", + "in": "path", + "description": "ID of CCF member who signed and submitted this ballot.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Proposals.Ballot" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Ballots_Get": { + "$ref": "./examples/Ballots_Get.json" + } + } + } + }, + "/gov/members/proposals:create": { + "post": { + "operationId": "Proposals_Create", + "description": "Submit a proposed change to the service. This will be assigned an ID by the service. Submitting the same signature (including signed COSE headers such as created_at) multiple times will be treated as a single idempotent operation, returning a single created proposal (or an error if it is no longer available). Any change to the request body will be treated as a new, separate proposal.", + "consumes": [ + "application/cose" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "$ref": "#/parameters/CoseSignature.body" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Proposals.Proposal" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Proposals_Create": { + "$ref": "./examples/Proposals_Create.json" + } + } + } + }, + "/gov/members/state-digests/{memberId}:update": { + "post": { + "operationId": "StateDigests_Update", + "description": "Request that this member's stateDigest is updated to a fresher value. Only this member may update their own stateDigest. Returns the refreshed value.", + "consumes": [ + "application/cose" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "memberId", + "in": "path", + "description": "Identifier for member this stateDigest applies to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "$ref": "#/parameters/CoseSignature.body" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Acks.StateDigest" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "StateDigests_Update": { + "$ref": "./examples/StateDigests_Update.json" + } + } + } + }, + "/gov/members/state-digests/{memberId}:ack": { + "post": { + "operationId": "StateDigests_Acknowledge", + "description": "Submit a signed acknowledgement of a recent digest of the service status, to transition the member to Active.", + "consumes": [ + "application/cose" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "memberId", + "in": "path", + "description": "Identifier for member this stateDigest applies to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "$ref": "#/parameters/CoseSignature.body" + } + ], + "responses": { + "204": { + "description": "There is no content to send for this request, but the headers may be useful. ", + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "StateDigests_Acknowledge": { + "$ref": "./examples/StateDigests_Acknowledge.json" + } + } + } + }, + "/gov/members/state-digests/{memberId}": { + "get": { + "operationId": "StateDigests_Get", + "description": "Get the stateDigest assigned to the given member, which that member must sign to become active.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "memberId", + "in": "path", + "description": "Identifier for member this stateDigest applies to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Acks.StateDigest" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "StateDigests_Get": { + "$ref": "./examples/StateDigests_Get.json" + } + } + } + }, + "/gov/recovery/encrypted-shares/{memberId}": { + "get": { + "operationId": "EncryptedShares_Get", + "description": "Retrieve a member's recovery share, encrypted with that member's share-encryption key.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "memberId", + "in": "path", + "description": "ID of CCF member who this recovery share belongs to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Recovery.EncryptedRecoveryShare" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "EncryptedShares_Get": { + "$ref": "./examples/EncryptedShares_Get.json" + } + } + } + }, + "/gov/recovery/members/{memberId}:recover": { + "post": { + "operationId": "Shares_Submit", + "description": "Provide a recovery share for the purpose of completing a service recovery.", + "consumes": [ + "application/cose" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "memberId", + "in": "path", + "description": "Identifier for member this recovery state applies to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + { + "$ref": "#/parameters/CoseSignature.body" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Recovery.RecoveryResponse" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Shares_Submit": { + "$ref": "./examples/Shares_Submit.json" + } + } + } + }, + "/gov/service/constitution": { + "get": { + "operationId": "ServiceState_GetConstitution", + "description": "Retrieve the constitution which controls governance changes on this service.", + "produces": [ + "text/javascript", + "application/json" + ], + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.ConstitutionResponse" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetConstitution": { + "$ref": "./examples/ServiceState_GetConstitution.json" + } + } + } + }, + "/gov/service/info": { + "get": { + "operationId": "ServiceState_GetServiceInfo", + "description": "Returns general information about the service, including whether it is a recovery or original service.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.ServiceInfo" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetServiceInfo": { + "$ref": "./examples/ServiceState_GetServiceInfo.json" + } + } + } + }, + "/gov/service/javascript-app": { + "get": { + "operationId": "ServiceState_GetJsApp", + "description": "Retrieve details of Javascript application and execution engine.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.JsApp" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetJsApp": { + "$ref": "./examples/ServiceState_GetJsApp.json" + } + } + } + }, + "/gov/service/join-policy": { + "get": { + "operationId": "ServiceState_GetJoinPolicies", + "description": "Retrieve policy data which determines whether new nodes are permitted to join the service. This describes the hardware attestations which are acceptable to the service, demonstrating a joining node is running approved code.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.JoinPolicies" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetJoinPolicies": { + "$ref": "./examples/ServiceState_GetJoinPolicies.json" + } + } + } + }, + "/gov/service/jwk": { + "get": { + "operationId": "ServiceState_GetJwkInfo", + "description": "Returns information about OpenID Connect identity providers.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.JwkInfo" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetJwkInfo": { + "$ref": "./examples/ServiceState_GetJwkInfo.json" + } + } + } + }, + "/gov/service/members": { + "get": { + "operationId": "ServiceState_ListMembers", + "description": "Retrieve list of all members who govern this service.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/PagedMember" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_ListMembers": { + "$ref": "./examples/ServiceState_ListMembers.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/gov/service/members/{memberId}": { + "get": { + "operationId": "ServiceState_GetMember", + "description": "Retrieve a single governing member, by ID.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "memberId", + "in": "path", + "description": "ID of CCF member who this object refers to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.Member" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetMember": { + "$ref": "./examples/ServiceState_GetMember.json" + } + } + } + }, + "/gov/service/nodes": { + "get": { + "operationId": "ServiceState_ListNodes", + "description": "Retrieve list of all nodes participating in this service.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/PagedNode" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_ListNodes": { + "$ref": "./examples/ServiceState_ListNodes.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/gov/service/nodes/{nodeId}": { + "get": { + "operationId": "ServiceState_GetNode", + "description": "Retrieve a single node, by ID.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "nodeId", + "in": "path", + "description": "ID of CCF node who this object refers to.", + "required": true, + "type": "string", + "pattern": "^[a-f0-9]{64}$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/ServiceState.Node" + }, + "headers": { + "x-ms-ccf-transaction-id": { + "type": "string", + "description": "Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.", + "pattern": "^[0-9]+\\.[0-9]+$" + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "ServiceState_GetNode": { + "$ref": "./examples/ServiceState_GetNode.json" + } + } + } + }, + "/gov/service/transactions/{transactionId}": { + "get": { + "operationId": "Transactions_Get", + "description": "Get status of transaction by transaction ID, to determine whether it has committed.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "transactionId", + "in": "path", + "description": "Identifier of the requested transaction.", + "required": true, + "type": "string", + "pattern": "^[0-9]+\\.[0-9]+$" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Transactions.Transaction" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Transactions_Get": { + "$ref": "./examples/Transactions_Get.json" + } + } + } + }, + "/gov/service/transactions/commit": { + "get": { + "operationId": "Transactions_GetCommit", + "description": "Get latest committed transaction.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/Transactions.CommittedTransaction" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/Azure.Core.Foundations.ErrorResponse" + }, + "headers": { + "x-ms-error-code": { + "type": "string", + "description": "String error code indicating what went wrong." + } + } + } + }, + "x-ms-examples": { + "Transactions_GetCommit": { + "$ref": "./examples/Transactions_GetCommit.json" + } + } + } + } + }, + "definitions": { + "Acks.StateDigest": { + "type": "object", + "description": "A compact summary of the service's state up to a certain point in time, updated and signed by members to indicate their participation in and approval of the service.", + "properties": { + "digest": { + "type": "string", + "description": "Hex-encoding of SHA-256 hash of the root of the service's merkle tree. This should be signed by a new member and submitted as an ACK to mark that member as Active.", + "pattern": "^[a-f0-9]{64}$" + } + }, + "required": [ + "digest" + ] + }, + "Azure.Core.Foundations.Error": { + "type": "object", + "description": "The error object.", + "properties": { + "code": { + "type": "string", + "description": "One of a server-defined set of error codes." + }, + "message": { + "type": "string", + "description": "A human-readable representation of the error." + }, + "target": { + "type": "string", + "description": "The target of the error." + }, + "details": { + "type": "array", + "description": "An array of details about specific errors that led to this reported error.", + "items": { + "$ref": "#/definitions/Azure.Core.Foundations.Error" + }, + "x-ms-identifiers": [] + }, + "innererror": { + "$ref": "#/definitions/Azure.Core.Foundations.InnerError", + "description": "An object containing more specific information than the current object about the error." + } + }, + "required": [ + "code", + "message" + ] + }, + "Azure.Core.Foundations.ErrorResponse": { + "type": "object", + "description": "A response containing error details.", + "properties": { + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "The error object." + } + }, + "required": [ + "error" + ] + }, + "Azure.Core.Foundations.InnerError": { + "type": "object", + "description": "An object containing more specific information about the error. As per Microsoft One API guidelines - https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md#7102-error-condition-responses.", + "properties": { + "code": { + "type": "string", + "description": "One of a server-defined set of error codes." + }, + "innererror": { + "$ref": "#/definitions/Azure.Core.Foundations.InnerError", + "description": "Inner error." + } + } + }, + "PagedMember": { + "type": "object", + "description": "Paged collection of Member items", + "properties": { + "value": { + "type": "array", + "description": "The Member items on this page", + "items": { + "$ref": "#/definitions/ServiceState.Member" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "PagedNode": { + "type": "object", + "description": "Paged collection of Node items", + "properties": { + "value": { + "type": "array", + "description": "The Node items on this page", + "items": { + "$ref": "#/definitions/ServiceState.Node" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "PagedProposal": { + "type": "object", + "description": "Paged collection of Proposal items", + "properties": { + "value": { + "type": "array", + "description": "The Proposal items on this page", + "items": { + "$ref": "#/definitions/Proposals.Proposal" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "Proposals.Action": { + "type": "object", + "description": "A single step in a proposed change to the service.", + "properties": { + "name": { + "type": "string", + "description": "The name of the action to perform. This should match an action defined in the service's constitution, so that it can be invoked by the `apply` function of the constitution if the proposal is accepted." + }, + "args": { + "description": "Arguments to modify the behavior of this action. The schema is determined by the action implementation, and should be validated by a `validate` call in the constitution." + } + }, + "required": [ + "name" + ] + }, + "Proposals.Ballot": { + "type": "object", + "description": "The source script of an executable vote from a member, regarding a proposed change to the service.", + "properties": { + "script": { + "type": "string", + "description": "The script to execute, returning the voter's support of this proposal." + } + }, + "required": [ + "script" + ] + }, + "Proposals.FailureInfo": { + "type": "object", + "description": "Description of why governance execution failed.", + "properties": { + "reason": { + "type": "string", + "description": "Error message describing reason for failure." + }, + "trace": { + "type": "string", + "description": "Call stack showing where failure occurred, if available." + } + }, + "required": [ + "reason" + ] + }, + "Proposals.MemberVotes": { + "type": "object", + "description": "Each key is a memberId, and the corresponding value is the result of their ballot.", + "additionalProperties": { + "type": "boolean" + } + }, + "Proposals.Proposal": { + "type": "object", + "description": "Description of a proposed change to the service.", + "properties": { + "proposalId": { + "$ref": "#/definitions/proposalId", + "description": "Unique ID assigned to this proposal at its submission, by the service." + }, + "proposerId": { + "$ref": "#/definitions/memberId", + "description": "ID of CCF member who signed and created this proposal." + }, + "proposalState": { + "$ref": "#/definitions/Proposals.ProposalState", + "description": "Current state of this proposal." + }, + "ballotCount": { + "$ref": "#/definitions/safeuint", + "description": "Count of how many ballots have been submitted for this proposal." + }, + "finalVotes": { + "$ref": "#/definitions/Proposals.MemberVotes", + "description": "If a proposal is not open, then this contains the result of each ballot when the proposal transitioned from open." + }, + "voteFailures": { + "$ref": "#/definitions/Proposals.VoteFailures", + "description": "This will be populated with a description of any ballots which failed to execute." + }, + "failure": { + "$ref": "#/definitions/Proposals.FailureInfo", + "description": "If proposalState is Failure, then this will describe why the proposal failed." + } + }, + "required": [ + "proposalId", + "proposerId", + "proposalState", + "ballotCount" + ] + }, + "Proposals.ProposalActions": { + "type": "object", + "description": "The actions contained in a proposal, describing the proposal's changes.", + "properties": { + "actions": { + "type": "array", + "description": "A list of actions to apply. Each action is considered, in order, for both proposal and execution of the proposal. All actions are validated and, if the proposal is accepted, applied atomically.", + "items": { + "$ref": "#/definitions/Proposals.Action" + }, + "x-ms-identifiers": [] + } + }, + "required": [ + "actions" + ] + }, + "Proposals.ProposalState": { + "type": "string", + "description": "Possible states for a proposal.", + "enum": [ + "Open", + "Accepted", + "Withdrawn", + "Rejected", + "Failed", + "Dropped" + ], + "x-ms-enum": { + "name": "ProposalState", + "modelAsString": true, + "values": [ + { + "name": "Open", + "value": "Open", + "description": "Proposal is active and can be voted on." + }, + { + "name": "Accepted", + "value": "Accepted", + "description": "Proposal passed a successful vote and was enacted." + }, + { + "name": "Withdrawn", + "value": "Withdrawn", + "description": "Proposal was removed by proposing member. Will never be enacted." + }, + { + "name": "Rejected", + "value": "Rejected", + "description": "Proposal was rejected by vote. Will never be enacted." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Proposal passed a successful vote, but its proposed actions failed. Will never be enacted." + }, + { + "name": "Dropped", + "value": "Dropped", + "description": "Proposal was open when its semantics were potentially changed (code or constitution were modified), so it was automatically invalidated." + } + ] + } + }, + "Proposals.VoteFailures": { + "type": "object", + "description": "Each key is a memberId, and the corresponding value explains why execution of their ballot failed.", + "additionalProperties": { + "$ref": "#/definitions/Proposals.FailureInfo" + } + }, + "Recovery.EncryptedRecoveryShare": { + "type": "object", + "description": "A share of a recovery key, granted for a specific recovery member, and encrypted with that member's share-encryption key. This is safe to share in the ledger or amongst untrusted callers, as only the intended member will be able to decrypt and access the secret content.", + "properties": { + "encryptedShare": { + "type": "string", + "format": "byte", + "description": "Base-64 encoding of a member's encrypted share." + } + }, + "required": [ + "encryptedShare" + ] + }, + "Recovery.Member": { + "type": "object", + "description": "Recovery-specific details for a given member." + }, + "Recovery.RecoveryResponse": { + "type": "object", + "description": "Response to a submitted recovery share.", + "properties": { + "message": { + "type": "string", + "description": "Human-readable description of current recovery progress." + }, + "submittedCount": { + "$ref": "#/definitions/safeuint", + "description": "Count of how many accepted member shares have been submitted, including the current request." + }, + "recoveryThreshold": { + "$ref": "#/definitions/safeuint", + "description": "Count of how many member shares are required to initiate the end-of-recovery procedure." + } + }, + "required": [ + "message", + "submittedCount", + "recoveryThreshold" + ] + }, + "Recovery.RecoveryShare": { + "type": "object", + "description": "Container for a member's raw recovery share. This should be carefully guarded, and only submitted to a trusted service over a secure channel, for the purposes of recovery.", + "properties": { + "share": { + "type": "string", + "format": "byte", + "description": "Base-64 encoding of a member's raw recovery share (unencrypted)." + } + }, + "required": [ + "share" + ] + }, + "ServiceState.ConstitutionResponse": { + "type": "object", + "description": "Constitution used to make governance decisions on the service. All governance changes are presented as proposals which must be validated, approved, and applied by the code in this constitution.", + "properties": { + "constitution": { + "type": "string", + "description": "Javascript source code of constitution." + } + }, + "required": [ + "constitution" + ] + }, + "ServiceState.ForwardingRequired": { + "type": "string", + "description": "Describes the forwarding behavior of a specific endpoint. Write requests cannot be executed on a backup, so will generally be forwarded by any backup node which receives them to the current primary. Future requests on the same session may then be forwarded to maintain session consistency.", + "enum": [ + "Sometimes", + "Always", + "Never" + ], + "x-ms-enum": { + "name": "ForwardingRequired", + "modelAsString": true, + "values": [ + { + "name": "Sometimes", + "value": "Sometimes", + "description": "Indicates that this request should be forwarded if-and-only-if it is needed to maintain session consistency. If stale reads are acceptable then they can be completed on a backup, and the request will not be forwarded. This should be the default behavior for read-only endpoints." + }, + { + "name": "Always", + "value": "Always", + "description": "Indicates that this request should always be forwarded. This will trigger forwarding of any additional requests on the same session, even those marked ForwardRequired::Sometimes. This should be the default behavior for any endpoint which writes to the Key-Value store." + }, + { + "name": "Never", + "value": "Never", + "description": "Indicates endpoints which will never be forwarded, even when this will result in a break of session consistency. This should be used only to access node-local information, or when weaker consistency is acceptable." + } + ] + } + }, + "ServiceState.JoinPolicies": { + "type": "object", + "description": "Collection of all policies which determine currently acceptable nodes, across multiple platforms.", + "properties": { + "sgx": { + "$ref": "#/definitions/ServiceState.JoinPolicy", + "description": "Policy applied to nodes running in SGX enclaves." + }, + "snp": { + "$ref": "#/definitions/ServiceState.SnpJoinPolicy", + "description": "Policy applied to nodes running in AMD SEV-SNP containers." + } + }, + "required": [ + "sgx", + "snp" + ] + }, + "ServiceState.JoinPolicy": { + "type": "object", + "description": "Describes what a joining node must present, in order to join the service.", + "properties": { + "measurements": { + "type": "array", + "description": "Code measurements of acceptable enclaves.", + "items": { + "type": "string", + "format": "byte" + } + } + }, + "required": [ + "measurements" + ] + }, + "ServiceState.JsApp": { + "type": "object", + "description": "Describes the currently installed JavaScript application.", + "properties": { + "endpoints": { + "type": "object", + "description": "The collection of endpoints exposed by the application. Keyed by path.", + "additionalProperties": { + "$ref": "#/definitions/ServiceState.JsOperations" + } + } + }, + "required": [ + "endpoints" + ] + }, + "ServiceState.JsEndpointInfo": { + "type": "object", + "description": "Describes an endpoint implemented by a Javascript handler.", + "properties": { + "jsModule": { + "type": "string", + "description": "The name of the module where the endpoint function is located." + }, + "jsFunction": { + "type": "string", + "description": "The name of the exported function which implements this endpoint." + }, + "forwardingRequired": { + "$ref": "#/definitions/ServiceState.ForwardingRequired", + "description": "Describes whether requests to this endpoint should be forwarded to the primary or executed on backups." + }, + "authnPolicies": { + "type": "array", + "description": "The authentication policies which restrict access to this endpoint", + "items": { + "type": "string" + } + }, + "mode": { + "$ref": "#/definitions/ServiceState.JsExecMode", + "description": "Describes how this endpoint should be executed." + }, + "openApi": { + "type": "object", + "description": "An OpenAPI Operation object (https://swagger.io/specification/#operation-object) describing this operation. This is merged into the auto-generated OpenAPI to describe the current application's API.", + "additionalProperties": {} + } + }, + "required": [ + "jsModule", + "jsFunction", + "forwardingRequired", + "authnPolicies", + "mode", + "openApi" + ] + }, + "ServiceState.JsExecMode": { + "type": "string", + "description": "Describes the execution requirements of a specific endpoint.", + "enum": [ + "ReadWrite", + "ReadOnly", + "Historical" + ], + "x-ms-enum": { + "name": "JsExecMode", + "modelAsString": true, + "values": [ + { + "name": "ReadWrite", + "value": "ReadWrite", + "description": "Indicates that the endpoint does (or may) produces writes to the Key-Value store." + }, + { + "name": "ReadOnly", + "value": "ReadOnly", + "description": "Indicates that the endpoint is a pure read, and will never write to the Key-Value store. Note that this includes endpoints which only access node-local state, and do not read from the Key-Value store at all." + }, + { + "name": "Historical", + "value": "Historical", + "description": "Indicates that the endpoint operates over a historical write to the Key-Value store rather than the latest, current state. These endpoints are also read-only, and may not produce writes." + } + ] + } + }, + "ServiceState.JsOperations": { + "type": "object", + "description": "The collection of operations available on each path. Keyed by HTTP method.", + "additionalProperties": { + "$ref": "#/definitions/ServiceState.JsEndpointInfo" + } + }, + "ServiceState.JwkInfo": { + "type": "object", + "description": "Describes what Javascript Web Tokens (JWTs) are accepted by the service, and how they will be validated.", + "properties": { + "issuers": { + "type": "object", + "description": "Collection of JWT issuers. Keyed by issuer ID.", + "additionalProperties": { + "$ref": "#/definitions/ServiceState.JwtIssuer" + } + }, + "caCertBundles": { + "type": "object", + "description": "Collection of CAs used to authenticate connections with issuers. Keyed by governance-controlled bundle names.", + "additionalProperties": { + "$ref": "#/definitions/ServiceState.caCertBundle" + } + } + }, + "required": [ + "issuers", + "caCertBundles" + ] + }, + "ServiceState.JwtIssuer": { + "type": "object", + "description": "Description of a JWT issuer or identity provider that the current service will trust tokens from.", + "properties": { + "keyFilter": { + "$ref": "#/definitions/ServiceState.JwtIssuerKeyFilter", + "description": "Adds restrictions on whether keys should be accepted from this issuer." + }, + "keyPolicy": { + "type": "object", + "description": "Collection of claims which must be present in SGX attestation to permit updates from this issuer.", + "additionalProperties": { + "type": "string" + } + }, + "autoRefresh": { + "type": "boolean", + "description": "Whether this issuer's keys are periodically refreshed with a fetch from the current primary. If false, these will only be updated by governance." + }, + "caCertBundleName": { + "type": "string", + "description": "Name of bundle used to authenticate issuer when auto-refreshing." + } + }, + "required": [ + "keyFilter", + "autoRefresh" + ] + }, + "ServiceState.JwtIssuerKeyFilter": { + "type": "string", + "description": "Possible restrictions on what keys will be accepted from a JWT issuer.", + "enum": [ + "All", + "Sgx" + ], + "x-ms-enum": { + "name": "JwtIssuerKeyFilter", + "modelAsString": true, + "values": [ + { + "name": "All", + "value": "All", + "description": "Accepts any JWT issuer." + }, + { + "name": "Sgx", + "value": "Sgx", + "description": "Only accepts JWTs issued by a token provider running in SGX, which provides a suitable attestation and additional claims." + } + ] + } + }, + "ServiceState.Member": { + "type": "object", + "description": "Information on individual members within a consortium.", + "properties": { + "memberId": { + "$ref": "#/definitions/memberId", + "description": "ID of CCF member who this object refers to." + }, + "status": { + "$ref": "#/definitions/ServiceState.MemberStatus", + "description": "Current status of this member." + }, + "memberData": { + "description": "Arbitrary service-defined metadata about this member. May be used by constitution or application code, but will not affect any core framework decisions." + }, + "certificate": { + "$ref": "#/definitions/ServiceState.pem", + "description": "x509 certificate used as this member's identity." + } + }, + "required": [ + "memberId", + "status", + "certificate" + ] + }, + "ServiceState.MemberStatus": { + "type": "string", + "description": "Possible states for a CCF governing member.", + "enum": [ + "Accepted", + "Active" + ], + "x-ms-enum": { + "name": "MemberStatus", + "modelAsString": true, + "values": [ + { + "name": "Accepted", + "value": "Accepted", + "description": "Member has been approved to join the service, but have not yet submitted an ACK to indicate their participation. These members should not be considered by constitutions in quorum calculations, and their signed requests will be rejected until they become Active." + }, + { + "name": "Active", + "value": "Active", + "description": "Member has submitted a valid ACK and is a full voting participant." + } + ] + } + }, + "ServiceState.NetworkInterface": { + "type": "object", + "description": "Details of how to contact a CCF node. Each node may listen on multiple interfaces, for different kinds of traffic.", + "properties": { + "publishedAddress": { + "type": "string", + "description": "The network address where this node believes it is publicly accessible, in the format [:]." + }, + "protocol": { + "type": "string", + "description": "The application layer protocol which the node expects on this interface. Currently supports \"http1\" and \"http2\", more protocols may be added in future." + } + }, + "required": [ + "publishedAddress", + "protocol" + ] + }, + "ServiceState.Node": { + "type": "object", + "description": "Information on individual nodes within a service.", + "properties": { + "nodeId": { + "$ref": "#/definitions/nodeId", + "description": "ID of CCF node who this object refers to." + }, + "status": { + "$ref": "#/definitions/ServiceState.NodeStatus", + "description": "Current status of this node." + }, + "nodeData": { + "description": "Arbitrary service-defined metadata about this node. May be used by constitution or application code, but will not affect any core framework decisions." + }, + "certificate": { + "$ref": "#/definitions/ServiceState.pem", + "description": "x509 certificate containing this node's identity." + }, + "retiredCommitted": { + "type": "boolean", + "description": "This is false during node's normal operation. It transitions to true once the node has been retired, and that retirement has been committed by the service. At this point it is safe to terminate a node. Terminating a node any earlier may affect liveness of the service." + }, + "quoteInfo": { + "$ref": "#/definitions/ServiceState.QuoteInfo", + "description": "Contains this node's hardware attestation. This is generated during node startup, and must meet the current join policy restrictions for the node to successfully join a service." + }, + "rpcInterfaces": { + "type": "object", + "description": "A collection of interfaces by which this node may be contacted. Some may be limited to private networks, and others may be DNS names or internet-public network addresses. The keys are arbitrary strings determined by the node operator.", + "additionalProperties": { + "$ref": "#/definitions/ServiceState.NetworkInterface" + } + } + }, + "required": [ + "nodeId", + "status", + "certificate", + "retiredCommitted", + "quoteInfo", + "rpcInterfaces" + ] + }, + "ServiceState.NodeStatus": { + "type": "string", + "description": "Lifecycle state of a CCF node. Nodes will generally start as Pending, then transition to Trusted, then to Retired. They are only full participants in the service while they are Trusted.", + "enum": [ + "Pending", + "Trusted", + "Retired" + ], + "x-ms-enum": { + "name": "NodeStatus", + "modelAsString": true, + "values": [ + { + "name": "Pending", + "value": "Pending", + "description": "Indicates a node which has successfully completed a join request to the service (including attestation checks), but has not yet been approved by governance." + }, + { + "name": "Trusted", + "value": "Trusted", + "description": "Indicates a node which has been approved by governance, and is a full participant in the service." + }, + { + "name": "Retired", + "value": "Retired", + "description": "Indicates a node which has been removed from a service by a reconfiguration." + } + ] + } + }, + "ServiceState.QuoteInfo": { + "type": "object", + "description": "Common type for attestation information, describing the cryptographically-endorsed claim of what code is executing, and what platform it is executing on. Derived types contain platform-specific details.", + "properties": { + "format": { + "type": "string", + "description": "Discriminator property for QuoteInfo." + } + }, + "discriminator": "format", + "required": [ + "format" + ] + }, + "ServiceState.ServiceInfo": { + "type": "object", + "description": "General information about the current service.", + "properties": { + "status": { + "$ref": "#/definitions/ServiceState.ServiceStatus", + "description": "Lifetime stage of the service." + }, + "certificate": { + "$ref": "#/definitions/ServiceState.pem", + "description": "The current service identity. This is the public face of a secret key shared only by the nodes within the service, and should be used to authenticate TLS sessions with this service." + }, + "recoveryCount": { + "$ref": "#/definitions/safeuint", + "description": "Records how many predecessors this service has. While the service identity certificate will change on any recovery, this allows users to determine exactly how many such recoveries have occurred." + }, + "creationTransactionId": { + "$ref": "#/definitions/transactionId", + "description": "Transaction ID at which this service was first created. If this is a recovery of a previous service, this will indicate when the current service was recovered." + }, + "previousServiceCreationTransactionId": { + "$ref": "#/definitions/ServiceState.pem", + "description": "Transaction ID at which the predecessor service was created, if this service is a recovery. If this is an original service rather than a recovery, this will be omitted." + }, + "serviceData": { + "description": "Arbitrary service-defined metadata about this service. May be used by constitution or application code, but will not affect any core framework decisions." + }, + "configuration": { + "type": "object", + "description": "Lists governance-controlled configuration parameters of this service, which will be used by core framework code.", + "properties": { + "maximumNodeCertificateValidityDays": { + "$ref": "#/definitions/safeuint" + }, + "recentCoseProposalsWindowSize": { + "$ref": "#/definitions/safeuint" + } + }, + "required": [ + "maximumNodeCertificateValidityDays", + "recentCoseProposalsWindowSize" + ] + } + }, + "required": [ + "status", + "certificate", + "recoveryCount", + "creationTransactionId", + "configuration" + ] + }, + "ServiceState.ServiceStatus": { + "type": "string", + "description": "State machine values for current service lifetime. New services start in Opening, and transition to Open via a governance proposal. They will only accept user transactions on the `/app` endpoints once they are Open. Recovery services have additional states where they must wait for members to submit sufficient recovery shares to access the previous ledger secrets, and while they are decrypting and replaying the previous ledger contents.", + "enum": [ + "Opening", + "Open", + "WaitingForRecoveryShares", + "Recovering" + ], + "x-ms-enum": { + "name": "ServiceStatus", + "modelAsString": true, + "values": [ + { + "name": "Opening", + "value": "Opening", + "description": "Services which have not yet passed a `transition_service_to_open` proposal." + }, + { + "name": "Open", + "value": "Open", + "description": "Services which are operating normally and accepting user transactions." + }, + { + "name": "WaitingForRecoveryShares", + "value": "WaitingForRecoveryShares", + "description": "Recovered services which cannot yet access private state." + }, + { + "name": "Recovering", + "value": "Recovering", + "description": "Recovered services which are actively replaying transactions from previous service, to reach the same state." + } + ] + } + }, + "ServiceState.SgxQuoteInfo": { + "type": "object", + "description": "Attestation information for Intel SGX enclaves.", + "properties": { + "quote": { + "type": "string", + "format": "byte", + "description": "Base-64 encoded SGX quote." + }, + "endorsements": { + "type": "string", + "format": "byte", + "description": "Base-64 encoded SGX endorsements." + } + }, + "required": [ + "quote", + "endorsements" + ], + "allOf": [ + { + "$ref": "#/definitions/ServiceState.QuoteInfo" + } + ], + "x-ms-discriminator-value": "OE_SGX_v1" + }, + "ServiceState.SnpJoinPolicy": { + "type": "object", + "description": "Join policy fields specific to nodes running on AMD SEV-SNP hardware.", + "properties": { + "measurements": { + "type": "array", + "description": "Code measurements of acceptable enclaves.", + "items": { + "type": "string", + "format": "byte" + } + }, + "hostData": { + "type": "object", + "description": "Collection of acceptable host data values.", + "additionalProperties": { + "format": "byte", + "type": "string" + } + }, + "uvmEndorsements": { + "type": "object", + "description": "Collection of acceptable UVM endorsements.", + "additionalProperties": { + "format": "byte", + "type": "string" + } + } + }, + "required": [ + "measurements", + "hostData", + "uvmEndorsements" + ] + }, + "ServiceState.SnpQuoteInfo": { + "type": "object", + "description": "Attestation information for AMD SEV-SNP containers.", + "properties": { + "uvmEndorsements": { + "type": "string", + "format": "byte", + "description": "Base-64 encoded SNP UVM endorsements." + }, + "endorsedTcb": { + "type": "string", + "format": "byte", + "description": "Base-64 encoded SNP TCB endorsements." + } + }, + "required": [ + "uvmEndorsements", + "endorsedTcb" + ], + "allOf": [ + { + "$ref": "#/definitions/ServiceState.QuoteInfo" + } + ], + "x-ms-discriminator-value": "AMD_SEV_SNP_v1" + }, + "ServiceState.caCertBundle": { + "type": "string", + "description": "Chain of endorsed certificates (PEM format) leading to a CA." + }, + "ServiceState.pem": { + "type": "string", + "description": "PEM encoding of a cryptographic identifier. Contains a base64-encoded payload wrapped in content type identifiers." + }, + "Transactions.CommittedTransaction": { + "type": "object", + "description": "Description of latest committed transaction.", + "properties": { + "transactionId": { + "$ref": "#/definitions/transactionId", + "description": "Identifier of committed transaction." + }, + "status": { + "$ref": "#/definitions/Transactions.TransactionStatus", + "description": "Status of this transaction." + } + }, + "required": [ + "transactionId", + "status" + ] + }, + "Transactions.NamedTransaction": { + "type": "object", + "description": "Description of a named transaction's current state.", + "properties": { + "status": { + "$ref": "#/definitions/Transactions.TransactionStatus", + "description": "Status of this transaction." + } + }, + "required": [ + "status" + ] + }, + "Transactions.Transaction": { + "type": "object", + "description": "Common transaction information.", + "properties": { + "status": { + "$ref": "#/definitions/Transactions.TransactionStatus", + "description": "Status of this transaction." + } + }, + "required": [ + "status" + ] + }, + "Transactions.TransactionStatus": { + "type": "string", + "description": "Possible states for a CCF transaction. See docs for details: https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#checking-for-commit", + "enum": [ + "Unknown", + "Pending", + "Committed", + "Invalid" + ], + "x-ms-enum": { + "name": "TransactionStatus", + "modelAsString": true, + "values": [ + { + "name": "Unknown", + "value": "Unknown", + "description": "This is not a transaction the current node knows, but could exist in future. This may be returned when a transaction is created on one node then immediately queried on another, before it has been replicated." + }, + { + "name": "Pending", + "value": "Pending", + "description": "This transaction is known on the current node, but has not yet been committed. This is expected to be a temporary state." + }, + { + "name": "Committed", + "value": "Committed", + "description": "This transaction is known on the current node, and known to be committed. This means it has been replicated to a quorum of nodes, so will persist through future elections. Committed is a terminal state of this state machine." + }, + { + "name": "Invalid", + "value": "Invalid", + "description": "This transaction ID will never commit in the current service, because it contains a different term than a known transaction with the same sequence number. This can occur for a transaction ID returned from the service (ie - which was previously Unknown or Pending), if that transaction is lost during a consensus election. This should be rare. Invalid is a terminal state of this state machine." + } + ] + } + }, + "Versions": { + "type": "string", + "enum": [ + "2023-06-01-preview" + ], + "x-ms-enum": { + "name": "Versions", + "modelAsString": true + } + }, + "memberId": { + "type": "string", + "description": "Hex encoding of SHA-256 of a member certificate's fingerprint.", + "pattern": "^[a-f0-9]{64}$" + }, + "nodeId": { + "type": "string", + "description": "Hex encoding of SHA-256 of a node's public key.", + "pattern": "^[a-f0-9]{64}$" + }, + "proposalId": { + "type": "string", + "description": "Hex encoding of SHA-256 of proposed actions and merkle root of store at proposal creation. Unlike other IDs, this is generated on the service and will not be known in advance.", + "pattern": "^[a-f0-9]{64}$" + }, + "safeuint": { + "type": "integer", + "format": "int64", + "description": "A non-negative JSON-safe integer (ie max is 2^53 - 1)", + "minimum": 0 + }, + "transactionId": { + "type": "string", + "description": "Uniquely identifies an atomic transaction within a CCF service. Composed of a term number and sequence number. Sequence numbers increase monotonically, apart from during elections where the service may reuse an existing sequence number. Each election will result in a new, higher term number being used for the conflicting and future sequence numbers.", + "pattern": "^[0-9]+\\.[0-9]+$" + }, + "userId": { + "type": "string", + "description": "Hex encoding of SHA-256 of user certificate's fingerprint.", + "pattern": "^[a-f0-9]{64}$" + } + }, + "parameters": { + "Azure.Core.Foundations.ApiVersionParameter": { + "name": "api-version", + "in": "query", + "description": "The API version to use for this operation.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method", + "x-ms-client-name": "apiVersion" + }, + "CoseSignature.body": { + "name": "body", + "in": "body", + "description": "A raw CoseSign1 signature. See CCF docs for required headers and body schema: https://microsoft.github.io/CCF/main/use_apps/issue_commands.html#cose-schemas", + "required": true, + "schema": { + "type": "string", + "format": "binary" + }, + "x-ms-parameter-location": "method" + } + } +} diff --git a/doc/use_apps/issue_commands.rst b/doc/use_apps/issue_commands.rst index a1e86c50701e..45c082acc510 100644 --- a/doc/use_apps/issue_commands.rst +++ b/doc/use_apps/issue_commands.rst @@ -70,7 +70,7 @@ Creating a new proposal: :align: left * - Operation - - ``POST /gov/members/proposals`` + - ``POST /gov/members/proposals:create`` * - Protected headers - | ``ccf.gov.msg.type = proposal`` | ``ccf.gov.msg.created_at = `` @@ -146,7 +146,7 @@ Submitting recovery share: :align: left * - Operation - - ``POST /gov/members/members/{memberId}:recover`` + - ``POST /gov/recovery/members/{memberId}:recover`` * - Protected headers - | ``ccf.gov.msg.type = encrypted_recovery_share`` | ``ccf.gov.msg.created_at = `` diff --git a/js/ccf-app/package.json b/js/ccf-app/package.json index 46a8d6880455..b20f98da4be9 100644 --- a/js/ccf-app/package.json +++ b/js/ccf-app/package.json @@ -25,11 +25,11 @@ "chai": "^4.3.4", "colors": "1.4.0", "cross-env": "^7.0.3", + "get-func-name": "3.0.0", "mocha": "^10.0.0", "node-forge": "^1.2.0", "ts-node": "^10.4.0", "typedoc": "^0.25.0", - "typescript": "^5.0.2", - "get-func-name": "3.0.0" + "typescript": "^5.0.2" } } diff --git a/scripts/ci-checks.sh b/scripts/ci-checks.sh index b8a1c9dfc45f..61c377a5107f 100755 --- a/scripts/ci-checks.sh +++ b/scripts/ci-checks.sh @@ -69,9 +69,9 @@ endgroup group "TypeScript, JavaScript, Markdown, TypeSpec, YAML and JSON format" npm install --loglevel=error --no-save prettier @typespec/prettier-plugin-typespec 1>/dev/null if [ $FIX -ne 0 ]; then - git ls-files | grep -e '\.ts$' -e '\.js$' -e '\.md$' -e '\.yaml$' -e '\.yml$' -e '\.json$' | grep -v -e 'tests/sandbox/' -e 'src/node/gov/.*\.json$' | xargs npx prettier --write + git ls-files | grep -e '\.ts$' -e '\.js$' -e '\.md$' -e '\.yaml$' -e '\.yml$' -e '\.json$' | grep -v -e 'tests/sandbox/' | xargs npx prettier --write else - git ls-files | grep -e '\.ts$' -e '\.js$' -e '\.md$' -e '\.yaml$' -e '\.yml$' -e '\.json$' | grep -v -e 'tests/sandbox/' -e 'src/node/gov/.*\.json$' | xargs npx prettier --check + git ls-files | grep -e '\.ts$' -e '\.js$' -e '\.md$' -e '\.yaml$' -e '\.yml$' -e '\.json$' | grep -v -e 'tests/sandbox/' | xargs npx prettier --check fi endgroup diff --git a/src/node/gov/2023-06-01-preview.json b/src/node/gov/2023-06-01-preview.json deleted file mode 100644 index 5bcff5beb693..000000000000 --- a/src/node/gov/2023-06-01-preview.json +++ /dev/null @@ -1 +0,0 @@ -{"swagger":"2.0","info":{"title":"Managed CCF Governance","version":"2023-06-01-preview","x-typespec-generated":[{"emitter":"@azure-tools/typespec-autorest"}]},"schemes":["https"],"produces":["application/json"],"consumes":["application/json"],"tags":[],"paths":{"/gov/members/proposals":{"get":{"operationId":"Proposals_List","description":"Returns all current proposed changes to the service. Note that non-open proposals (ie - those which have already been accepted, rejected, withdrawn, etc) are not returned.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/PagedProposal"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Proposals_List":{"$ref":"./examples/Proposals_List.json"}},"x-ms-pageable":{"nextLinkName":"nextLink"}}},"/gov/members/proposals/{proposalId}:withdraw":{"post":{"operationId":"Proposals_Withdraw","description":"Withdraw an existing proposal. Only the original proposer is permitted to withdraw.","consumes":["application/cose"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"proposalId","in":"path","description":"Unique ID assigned to this proposal at its submission, by the service.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"$ref":"#/parameters/CoseSignature.body"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Proposals.Proposal"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Proposals_Withdraw":{"$ref":"./examples/Proposals_Withdraw.json"}}}},"/gov/members/proposals/{proposalId}":{"get":{"operationId":"Proposals_Get","description":"Returns a summary of a single proposed change to the service.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"proposalId","in":"path","description":"Unique ID assigned to this proposal at its submission, by the service.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Proposals.Proposal"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Proposals_Get":{"$ref":"./examples/Proposals_Get.json"}}}},"/gov/members/proposals/{proposalId}/actions":{"get":{"operationId":"Proposals_GetActions","description":"Returns actions contained in a proposal.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"proposalId","in":"path","description":"Unique ID assigned to this proposal at its submission, by the service.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Proposals.ProposalActions"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Proposals_GetActions":{"$ref":"./examples/Proposals_GetActions.json"}}}},"/gov/members/proposals/{proposalId}/ballots/{memberId}:submit":{"post":{"operationId":"Ballots_Submit","description":"Submit an executable ballot for a specific proposal. This may be as simple as `return true` to vote in favour, or contain reads from the KV and conditions on the proposal contents.","consumes":["application/cose"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"proposalId","in":"path","description":"Unique ID assigned to this proposal at its submission, by the service.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"name":"memberId","in":"path","description":"ID of CCF member who signed and submitted this ballot.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"$ref":"#/parameters/CoseSignature.body"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Proposals.Proposal"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Ballots_Submit":{"$ref":"./examples/Ballots_Submit.json"}}}},"/gov/members/proposals/{proposalId}/ballots/{memberId}":{"get":{"operationId":"Ballots_Get","description":"Returns a member's submitted ballot.","produces":["text/javascript","application/json"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"proposalId","in":"path","description":"Unique ID assigned to this proposal at its submission, by the service.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"name":"memberId","in":"path","description":"ID of CCF member who signed and submitted this ballot.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Proposals.Ballot"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Ballots_Get":{"$ref":"./examples/Ballots_Get.json"}}}},"/gov/members/proposals:create":{"post":{"operationId":"Proposals_Create","description":"Submit a proposed change to the service. This will be assigned an ID by the service. Submitting the same signature (including signed COSE headers such as created_at) multiple times will be treated as a single idempotent operation, returning a single created proposal (or an error if it is no longer available). Any change to the request body will be treated as a new, separate proposal.","consumes":["application/cose"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"$ref":"#/parameters/CoseSignature.body"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Proposals.Proposal"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Proposals_Create":{"$ref":"./examples/Proposals_Create.json"}}}},"/gov/members/state-digests/{memberId}:update":{"post":{"operationId":"StateDigests_Update","description":"Request that this member's stateDigest is updated to a fresher value. Only this member may update their own stateDigest. Returns the refreshed value.","consumes":["application/cose"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"memberId","in":"path","description":"Identifier for member this stateDigest applies to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"$ref":"#/parameters/CoseSignature.body"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Acks.StateDigest"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"StateDigests_Update":{"$ref":"./examples/StateDigests_Update.json"}}}},"/gov/members/state-digests/{memberId}:ack":{"post":{"operationId":"StateDigests_Acknowledge","description":"Submit a signed acknowledgement of a recent digest of the service status, to transition the member to Active.","consumes":["application/cose"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"memberId","in":"path","description":"Identifier for member this stateDigest applies to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"$ref":"#/parameters/CoseSignature.body"}],"responses":{"204":{"description":"There is no content to send for this request, but the headers may be useful. ","headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction where this request produced a write on the service. This uniquely identifies the submitted request, and can be used to confirm that the request becomes committed.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"StateDigests_Acknowledge":{"$ref":"./examples/StateDigests_Acknowledge.json"}}}},"/gov/members/state-digests/{memberId}":{"get":{"operationId":"StateDigests_Get","description":"Get the stateDigest assigned to the given member, which that member must sign to become active.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"memberId","in":"path","description":"Identifier for member this stateDigest applies to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Acks.StateDigest"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"StateDigests_Get":{"$ref":"./examples/StateDigests_Get.json"}}}},"/gov/recovery/encrypted-shares/{memberId}":{"get":{"operationId":"EncryptedShares_Get","description":"Retrieve a member's recovery share, encrypted with that member's share-encryption key.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"memberId","in":"path","description":"ID of CCF member who this recovery share belongs to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Recovery.EncryptedRecoveryShare"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"EncryptedShares_Get":{"$ref":"./examples/EncryptedShares_Get.json"}}}},"/gov/recovery/members/{memberId}:recover":{"post":{"operationId":"Shares_Submit","description":"Provide a recovery share for the purpose of completing a service recovery.","consumes":["application/cose"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"memberId","in":"path","description":"Identifier for member this recovery state applies to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"},{"$ref":"#/parameters/CoseSignature.body"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Recovery.RecoveryResponse"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Shares_Submit":{"$ref":"./examples/Shares_Submit.json"}}}},"/gov/service/constitution":{"get":{"operationId":"ServiceState_GetConstitution","description":"Retrieve the constitution which controls governance changes on this service.","produces":["text/javascript","application/json"],"parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.ConstitutionResponse"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetConstitution":{"$ref":"./examples/ServiceState_GetConstitution.json"}}}},"/gov/service/info":{"get":{"operationId":"ServiceState_GetServiceInfo","description":"Returns general information about the service, including whether it is a recovery or original service.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.ServiceInfo"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetServiceInfo":{"$ref":"./examples/ServiceState_GetServiceInfo.json"}}}},"/gov/service/javascript-app":{"get":{"operationId":"ServiceState_GetJsApp","description":"Retrieve details of Javascript application and execution engine.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.JsApp"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetJsApp":{"$ref":"./examples/ServiceState_GetJsApp.json"}}}},"/gov/service/join-policy":{"get":{"operationId":"ServiceState_GetJoinPolicies","description":"Retrieve policy data which determines whether new nodes are permitted to join the service. This describes the hardware attestations which are acceptable to the service, demonstrating a joining node is running approved code.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.JoinPolicies"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetJoinPolicies":{"$ref":"./examples/ServiceState_GetJoinPolicies.json"}}}},"/gov/service/jwk":{"get":{"operationId":"ServiceState_GetJwkInfo","description":"Returns information about OpenID Connect identity providers.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.JwkInfo"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetJwkInfo":{"$ref":"./examples/ServiceState_GetJwkInfo.json"}}}},"/gov/service/members":{"get":{"operationId":"ServiceState_ListMembers","description":"Retrieve list of all members who govern this service.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/PagedMember"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_ListMembers":{"$ref":"./examples/ServiceState_ListMembers.json"}},"x-ms-pageable":{"nextLinkName":"nextLink"}}},"/gov/service/members/{memberId}":{"get":{"operationId":"ServiceState_GetMember","description":"Retrieve a single governing member, by ID.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"memberId","in":"path","description":"ID of CCF member who this object refers to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.Member"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetMember":{"$ref":"./examples/ServiceState_GetMember.json"}}}},"/gov/service/nodes":{"get":{"operationId":"ServiceState_ListNodes","description":"Retrieve list of all nodes participating in this service.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/PagedNode"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_ListNodes":{"$ref":"./examples/ServiceState_ListNodes.json"}},"x-ms-pageable":{"nextLinkName":"nextLink"}}},"/gov/service/nodes/{nodeId}":{"get":{"operationId":"ServiceState_GetNode","description":"Retrieve a single node, by ID.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"nodeId","in":"path","description":"ID of CCF node who this object refers to.","required":true,"type":"string","pattern":"^[a-f0-9]{64}$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/ServiceState.Node"},"headers":{"x-ms-ccf-transaction-id":{"type":"string","description":"Identifier for transaction this response was read from. The service state may be altered by other write requests. Reads at the same transactionId describe a consistent single point in the service history.","pattern":"^[0-9]+\\.[0-9]+$"}}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"ServiceState_GetNode":{"$ref":"./examples/ServiceState_GetNode.json"}}}},"/gov/service/transactions/{transactionId}":{"get":{"operationId":"Transactions_Get","description":"Get status of transaction by transaction ID, to determine whether it has committed.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"},{"name":"transactionId","in":"path","description":"Identifier of the requested transaction.","required":true,"type":"string","pattern":"^[0-9]+\\.[0-9]+$"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Transactions.Transaction"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Transactions_Get":{"$ref":"./examples/Transactions_Get.json"}}}},"/gov/service/transactions/commit":{"get":{"operationId":"Transactions_GetCommit","description":"Get latest committed transaction.","parameters":[{"$ref":"#/parameters/Azure.Core.Foundations.ApiVersionParameter"}],"responses":{"200":{"description":"The request has succeeded.","schema":{"$ref":"#/definitions/Transactions.CommittedTransaction"}},"default":{"description":"An unexpected error response.","schema":{"$ref":"#/definitions/Azure.Core.Foundations.ErrorResponse"},"headers":{"x-ms-error-code":{"type":"string","description":"String error code indicating what went wrong."}}}},"x-ms-examples":{"Transactions_GetCommit":{"$ref":"./examples/Transactions_GetCommit.json"}}}}},"definitions":{"Acks.StateDigest":{"type":"object","description":"A compact summary of the service's state up to a certain point in time, updated and signed by members to indicate their participation in and approval of the service.","properties":{"digest":{"type":"string","description":"Hex-encoding of SHA-256 hash of the root of the service's merkle tree. This should be signed by a new member and submitted as an ACK to mark that member as Active.","pattern":"^[a-f0-9]{64}$"}},"required":["digest"]},"Azure.Core.Foundations.Error":{"type":"object","description":"The error object.","properties":{"code":{"type":"string","description":"One of a server-defined set of error codes."},"message":{"type":"string","description":"A human-readable representation of the error."},"target":{"type":"string","description":"The target of the error."},"details":{"type":"array","description":"An array of details about specific errors that led to this reported error.","items":{"$ref":"#/definitions/Azure.Core.Foundations.Error"},"x-ms-identifiers":[]},"innererror":{"$ref":"#/definitions/Azure.Core.Foundations.InnerError","description":"An object containing more specific information than the current object about the error."}},"required":["code","message"]},"Azure.Core.Foundations.ErrorResponse":{"type":"object","description":"A response containing error details.","properties":{"error":{"$ref":"#/definitions/Azure.Core.Foundations.Error","description":"The error object."}},"required":["error"]},"Azure.Core.Foundations.InnerError":{"type":"object","description":"An object containing more specific information about the error. As per Microsoft One API guidelines - https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md#7102-error-condition-responses.","properties":{"code":{"type":"string","description":"One of a server-defined set of error codes."},"innererror":{"$ref":"#/definitions/Azure.Core.Foundations.InnerError","description":"Inner error."}}},"PagedMember":{"type":"object","description":"Paged collection of Member items","properties":{"value":{"type":"array","description":"The Member items on this page","items":{"$ref":"#/definitions/ServiceState.Member"},"x-ms-identifiers":[]},"nextLink":{"type":"string","format":"uri","description":"The link to the next page of items"}},"required":["value"]},"PagedNode":{"type":"object","description":"Paged collection of Node items","properties":{"value":{"type":"array","description":"The Node items on this page","items":{"$ref":"#/definitions/ServiceState.Node"},"x-ms-identifiers":[]},"nextLink":{"type":"string","format":"uri","description":"The link to the next page of items"}},"required":["value"]},"PagedProposal":{"type":"object","description":"Paged collection of Proposal items","properties":{"value":{"type":"array","description":"The Proposal items on this page","items":{"$ref":"#/definitions/Proposals.Proposal"},"x-ms-identifiers":[]},"nextLink":{"type":"string","format":"uri","description":"The link to the next page of items"}},"required":["value"]},"Proposals.Action":{"type":"object","description":"A single step in a proposed change to the service.","properties":{"name":{"type":"string","description":"The name of the action to perform. This should match an action defined in the service's constitution, so that it can be invoked by the `apply` function of the constitution if the proposal is accepted."},"args":{"description":"Arguments to modify the behavior of this action. The schema is determined by the action implementation, and should be validated by a `validate` call in the constitution."}},"required":["name"]},"Proposals.Ballot":{"type":"object","description":"The source script of an executable vote from a member, regarding a proposed change to the service.","properties":{"script":{"type":"string","description":"The script to execute, returning the voter's support of this proposal."}},"required":["script"]},"Proposals.FailureInfo":{"type":"object","description":"Description of why governance execution failed.","properties":{"reason":{"type":"string","description":"Error message describing reason for failure."},"trace":{"type":"string","description":"Call stack showing where failure occurred, if available."}},"required":["reason"]},"Proposals.MemberVotes":{"type":"object","description":"Each key is a memberId, and the corresponding value is the result of their ballot.","additionalProperties":{"type":"boolean"}},"Proposals.Proposal":{"type":"object","description":"Description of a proposed change to the service.","properties":{"proposalId":{"$ref":"#/definitions/proposalId","description":"Unique ID assigned to this proposal at its submission, by the service."},"proposerId":{"$ref":"#/definitions/memberId","description":"ID of CCF member who signed and created this proposal."},"proposalState":{"$ref":"#/definitions/Proposals.ProposalState","description":"Current state of this proposal."},"ballotCount":{"$ref":"#/definitions/safeuint","description":"Count of how many ballots have been submitted for this proposal."},"finalVotes":{"$ref":"#/definitions/Proposals.MemberVotes","description":"If a proposal is not open, then this contains the result of each ballot when the proposal transitioned from open."},"voteFailures":{"$ref":"#/definitions/Proposals.VoteFailures","description":"This will be populated with a description of any ballots which failed to execute."},"failure":{"$ref":"#/definitions/Proposals.FailureInfo","description":"If proposalState is Failure, then this will describe why the proposal failed."}},"required":["proposalId","proposerId","proposalState","ballotCount"]},"Proposals.ProposalActions":{"type":"object","description":"The actions contained in a proposal, describing the proposal's changes.","properties":{"actions":{"type":"array","description":"A list of actions to apply. Each action is considered, in order, for both proposal and execution of the proposal. All actions are validated and, if the proposal is accepted, applied atomically.","items":{"$ref":"#/definitions/Proposals.Action"},"x-ms-identifiers":[]}},"required":["actions"]},"Proposals.ProposalState":{"type":"string","description":"Possible states for a proposal.","enum":["Open","Accepted","Withdrawn","Rejected","Failed","Dropped"],"x-ms-enum":{"name":"ProposalState","modelAsString":true,"values":[{"name":"Open","value":"Open","description":"Proposal is active and can be voted on."},{"name":"Accepted","value":"Accepted","description":"Proposal passed a successful vote and was enacted."},{"name":"Withdrawn","value":"Withdrawn","description":"Proposal was removed by proposing member. Will never be enacted."},{"name":"Rejected","value":"Rejected","description":"Proposal was rejected by vote. Will never be enacted."},{"name":"Failed","value":"Failed","description":"Proposal passed a successful vote, but its proposed actions failed. Will never be enacted."},{"name":"Dropped","value":"Dropped","description":"Proposal was open when its semantics were potentially changed (code or constitution were modified), so it was automatically invalidated."}]}},"Proposals.VoteFailures":{"type":"object","description":"Each key is a memberId, and the corresponding value explains why execution of their ballot failed.","additionalProperties":{"$ref":"#/definitions/Proposals.FailureInfo"}},"Recovery.EncryptedRecoveryShare":{"type":"object","description":"A share of a recovery key, granted for a specific recovery member, and encrypted with that member's share-encryption key. This is safe to share in the ledger or amongst untrusted callers, as only the intended member will be able to decrypt and access the secret content.","properties":{"encryptedShare":{"type":"string","format":"byte","description":"Base-64 encoding of a member's encrypted share."}},"required":["encryptedShare"]},"Recovery.Member":{"type":"object","description":"Recovery-specific details for a given member."},"Recovery.RecoveryResponse":{"type":"object","description":"Response to a submitted recovery share.","properties":{"message":{"type":"string","description":"Human-readable description of current recovery progress."},"submittedCount":{"$ref":"#/definitions/safeuint","description":"Count of how many accepted member shares have been submitted, including the current request."},"recoveryThreshold":{"$ref":"#/definitions/safeuint","description":"Count of how many member shares are required to initiate the end-of-recovery procedure."}},"required":["message","submittedCount","recoveryThreshold"]},"Recovery.RecoveryShare":{"type":"object","description":"Container for a member's raw recovery share. This should be carefully guarded, and only submitted to a trusted service over a secure channel, for the purposes of recovery.","properties":{"share":{"type":"string","format":"byte","description":"Base-64 encoding of a member's raw recovery share (unencrypted)."}},"required":["share"]},"ServiceState.ConstitutionResponse":{"type":"object","description":"Constitution used to make governance decisions on the service. All governance changes are presented as proposals which must be validated, approved, and applied by the code in this constitution.","properties":{"constitution":{"type":"string","description":"Javascript source code of constitution."}},"required":["constitution"]},"ServiceState.ForwardingRequired":{"type":"string","description":"Describes the forwarding behavior of a specific endpoint. Write requests cannot be executed on a backup, so will generally be forwarded by any backup node which receives them to the current primary. Future requests on the same session may then be forwarded to maintain session consistency.","enum":["Sometimes","Always","Never"],"x-ms-enum":{"name":"ForwardingRequired","modelAsString":true,"values":[{"name":"Sometimes","value":"Sometimes","description":"Indicates that this request should be forwarded if-and-only-if it is needed to maintain session consistency. If stale reads are acceptable then they can be completed on a backup, and the request will not be forwarded. This should be the default behavior for read-only endpoints."},{"name":"Always","value":"Always","description":"Indicates that this request should always be forwarded. This will trigger forwarding of any additional requests on the same session, even those marked ForwardRequired::Sometimes. This should be the default behavior for any endpoint which writes to the Key-Value store."},{"name":"Never","value":"Never","description":"Indicates endpoints which will never be forwarded, even when this will result in a break of session consistency. This should be used only to access node-local information, or when weaker consistency is acceptable."}]}},"ServiceState.JoinPolicies":{"type":"object","description":"Collection of all policies which determine currently acceptable nodes, across multiple platforms.","properties":{"sgx":{"$ref":"#/definitions/ServiceState.JoinPolicy","description":"Policy applied to nodes running in SGX enclaves."},"snp":{"$ref":"#/definitions/ServiceState.SnpJoinPolicy","description":"Policy applied to nodes running in AMD SEV-SNP containers."}},"required":["sgx","snp"]},"ServiceState.JoinPolicy":{"type":"object","description":"Describes what a joining node must present, in order to join the service.","properties":{"measurements":{"type":"array","description":"Code measurements of acceptable enclaves.","items":{"type":"string","format":"byte"}}},"required":["measurements"]},"ServiceState.JsApp":{"type":"object","description":"Describes the currently installed JavaScript application.","properties":{"endpoints":{"type":"object","description":"The collection of endpoints exposed by the application. Keyed by path.","additionalProperties":{"$ref":"#/definitions/ServiceState.JsOperations"}}},"required":["endpoints"]},"ServiceState.JsEndpointInfo":{"type":"object","description":"Describes an endpoint implemented by a Javascript handler.","properties":{"jsModule":{"type":"string","description":"The name of the module where the endpoint function is located."},"jsFunction":{"type":"string","description":"The name of the exported function which implements this endpoint."},"forwardingRequired":{"$ref":"#/definitions/ServiceState.ForwardingRequired","description":"Describes whether requests to this endpoint should be forwarded to the primary or executed on backups."},"authnPolicies":{"type":"array","description":"The authentication policies which restrict access to this endpoint","items":{"type":"string"}},"mode":{"$ref":"#/definitions/ServiceState.JsExecMode","description":"Describes how this endpoint should be executed."},"openApi":{"type":"object","description":"An OpenAPI Operation object (https://swagger.io/specification/#operation-object) describing this operation. This is merged into the auto-generated OpenAPI to describe the current application's API.","additionalProperties":{}}},"required":["jsModule","jsFunction","forwardingRequired","authnPolicies","mode","openApi"]},"ServiceState.JsExecMode":{"type":"string","description":"Describes the execution requirements of a specific endpoint.","enum":["ReadWrite","ReadOnly","Historical"],"x-ms-enum":{"name":"JsExecMode","modelAsString":true,"values":[{"name":"ReadWrite","value":"ReadWrite","description":"Indicates that the endpoint does (or may) produces writes to the Key-Value store."},{"name":"ReadOnly","value":"ReadOnly","description":"Indicates that the endpoint is a pure read, and will never write to the Key-Value store. Note that this includes endpoints which only access node-local state, and do not read from the Key-Value store at all."},{"name":"Historical","value":"Historical","description":"Indicates that the endpoint operates over a historical write to the Key-Value store rather than the latest, current state. These endpoints are also read-only, and may not produce writes."}]}},"ServiceState.JsOperations":{"type":"object","description":"The collection of operations available on each path. Keyed by HTTP method.","additionalProperties":{"$ref":"#/definitions/ServiceState.JsEndpointInfo"}},"ServiceState.JwkInfo":{"type":"object","description":"Describes what Javascript Web Tokens (JWTs) are accepted by the service, and how they will be validated.","properties":{"issuers":{"type":"object","description":"Collection of JWT issuers. Keyed by issuer ID.","additionalProperties":{"$ref":"#/definitions/ServiceState.JwtIssuer"}},"caCertBundles":{"type":"object","description":"Collection of CAs used to authenticate connections with issuers. Keyed by governance-controlled bundle names.","additionalProperties":{"$ref":"#/definitions/ServiceState.caCertBundle"}}},"required":["issuers","caCertBundles"]},"ServiceState.JwtIssuer":{"type":"object","description":"Description of a JWT issuer or identity provider that the current service will trust tokens from.","properties":{"keyFilter":{"$ref":"#/definitions/ServiceState.JwtIssuerKeyFilter","description":"Adds restrictions on whether keys should be accepted from this issuer."},"keyPolicy":{"type":"object","description":"Collection of claims which must be present in SGX attestation to permit updates from this issuer.","additionalProperties":{"type":"string"}},"autoRefresh":{"type":"boolean","description":"Whether this issuer's keys are periodically refreshed with a fetch from the current primary. If false, these will only be updated by governance."},"caCertBundleName":{"type":"string","description":"Name of bundle used to authenticate issuer when auto-refreshing."}},"required":["keyFilter","autoRefresh"]},"ServiceState.JwtIssuerKeyFilter":{"type":"string","description":"Possible restrictions on what keys will be accepted from a JWT issuer.","enum":["All","Sgx"],"x-ms-enum":{"name":"JwtIssuerKeyFilter","modelAsString":true,"values":[{"name":"All","value":"All","description":"Accepts any JWT issuer."},{"name":"Sgx","value":"Sgx","description":"Only accepts JWTs issued by a token provider running in SGX, which provides a suitable attestation and additional claims."}]}},"ServiceState.Member":{"type":"object","description":"Information on individual members within a consortium.","properties":{"memberId":{"$ref":"#/definitions/memberId","description":"ID of CCF member who this object refers to."},"status":{"$ref":"#/definitions/ServiceState.MemberStatus","description":"Current status of this member."},"memberData":{"description":"Arbitrary service-defined metadata about this member. May be used by constitution or application code, but will not affect any core framework decisions."},"certificate":{"$ref":"#/definitions/ServiceState.pem","description":"x509 certificate used as this member's identity."}},"required":["memberId","status","certificate"]},"ServiceState.MemberStatus":{"type":"string","description":"Possible states for a CCF governing member.","enum":["Accepted","Active"],"x-ms-enum":{"name":"MemberStatus","modelAsString":true,"values":[{"name":"Accepted","value":"Accepted","description":"Member has been approved to join the service, but have not yet submitted an ACK to indicate their participation. These members should not be considered by constitutions in quorum calculations, and their signed requests will be rejected until they become Active."},{"name":"Active","value":"Active","description":"Member has submitted a valid ACK and is a full voting participant."}]}},"ServiceState.NetworkInterface":{"type":"object","description":"Details of how to contact a CCF node. Each node may listen on multiple interfaces, for different kinds of traffic.","properties":{"publishedAddress":{"type":"string","description":"The network address where this node believes it is publicly accessible, in the format [:]."},"protocol":{"type":"string","description":"The application layer protocol which the node expects on this interface. Currently supports \"http1\" and \"http2\", more protocols may be added in future."}},"required":["publishedAddress","protocol"]},"ServiceState.Node":{"type":"object","description":"Information on individual nodes within a service.","properties":{"nodeId":{"$ref":"#/definitions/nodeId","description":"ID of CCF node who this object refers to."},"status":{"$ref":"#/definitions/ServiceState.NodeStatus","description":"Current status of this node."},"nodeData":{"description":"Arbitrary service-defined metadata about this node. May be used by constitution or application code, but will not affect any core framework decisions."},"certificate":{"$ref":"#/definitions/ServiceState.pem","description":"x509 certificate containing this node's identity."},"retiredCommitted":{"type":"boolean","description":"This is false during node's normal operation. It transitions to true once the node has been retired, and that retirement has been committed by the service. At this point it is safe to terminate a node. Terminating a node any earlier may affect liveness of the service."},"quoteInfo":{"$ref":"#/definitions/ServiceState.QuoteInfo","description":"Contains this node's hardware attestation. This is generated during node startup, and must meet the current join policy restrictions for the node to successfully join a service."},"rpcInterfaces":{"type":"object","description":"A collection of interfaces by which this node may be contacted. Some may be limited to private networks, and others may be DNS names or internet-public network addresses. The keys are arbitrary strings determined by the node operator.","additionalProperties":{"$ref":"#/definitions/ServiceState.NetworkInterface"}}},"required":["nodeId","status","certificate","retiredCommitted","quoteInfo","rpcInterfaces"]},"ServiceState.NodeStatus":{"type":"string","description":"Lifecycle state of a CCF node. Nodes will generally start as Pending, then transition to Trusted, then to Retired. They are only full participants in the service while they are Trusted.","enum":["Pending","Trusted","Retired"],"x-ms-enum":{"name":"NodeStatus","modelAsString":true,"values":[{"name":"Pending","value":"Pending","description":"Indicates a node which has successfully completed a join request to the service (including attestation checks), but has not yet been approved by governance."},{"name":"Trusted","value":"Trusted","description":"Indicates a node which has been approved by governance, and is a full participant in the service."},{"name":"Retired","value":"Retired","description":"Indicates a node which has been removed from a service by a reconfiguration."}]}},"ServiceState.QuoteInfo":{"type":"object","description":"Common type for attestation information, describing the cryptographically-endorsed claim of what code is executing, and what platform it is executing on. Derived types contain platform-specific details.","properties":{"format":{"type":"string","description":"Discriminator property for QuoteInfo."}},"discriminator":"format","required":["format"]},"ServiceState.ServiceInfo":{"type":"object","description":"General information about the current service.","properties":{"status":{"$ref":"#/definitions/ServiceState.ServiceStatus","description":"Lifetime stage of the service."},"certificate":{"$ref":"#/definitions/ServiceState.pem","description":"The current service identity. This is the public face of a secret key shared only by the nodes within the service, and should be used to authenticate TLS sessions with this service."},"recoveryCount":{"$ref":"#/definitions/safeuint","description":"Records how many predecessors this service has. While the service identity certificate will change on any recovery, this allows users to determine exactly how many such recoveries have occurred."},"creationTransactionId":{"$ref":"#/definitions/transactionId","description":"Transaction ID at which this service was first created. If this is a recovery of a previous service, this will indicate when the current service was recovered."},"previousServiceCreationTransactionId":{"$ref":"#/definitions/ServiceState.pem","description":"Transaction ID at which the predecessor service was created, if this service is a recovery. If this is an original service rather than a recovery, this will be omitted."},"serviceData":{"description":"Arbitrary service-defined metadata about this service. May be used by constitution or application code, but will not affect any core framework decisions."},"configuration":{"type":"object","description":"Lists governance-controlled configuration parameters of this service, which will be used by core framework code.","properties":{"maximumNodeCertificateValidityDays":{"$ref":"#/definitions/safeuint"},"recentCoseProposalsWindowSize":{"$ref":"#/definitions/safeuint"}},"required":["maximumNodeCertificateValidityDays","recentCoseProposalsWindowSize"]}},"required":["status","certificate","recoveryCount","creationTransactionId","configuration"]},"ServiceState.ServiceStatus":{"type":"string","description":"State machine values for current service lifetime. New services start in Opening, and transition to Open via a governance proposal. They will only accept user transactions on the `/app` endpoints once they are Open. Recovery services have additional states where they must wait for members to submit sufficient recovery shares to access the previous ledger secrets, and while they are decrypting and replaying the previous ledger contents.","enum":["Opening","Open","WaitingForRecoveryShares","Recovering"],"x-ms-enum":{"name":"ServiceStatus","modelAsString":true,"values":[{"name":"Opening","value":"Opening","description":"Services which have not yet passed a `transition_service_to_open` proposal."},{"name":"Open","value":"Open","description":"Services which are operating normally and accepting user transactions."},{"name":"WaitingForRecoveryShares","value":"WaitingForRecoveryShares","description":"Recovered services which cannot yet access private state."},{"name":"Recovering","value":"Recovering","description":"Recovered services which are actively replaying transactions from previous service, to reach the same state."}]}},"ServiceState.SgxQuoteInfo":{"type":"object","description":"Attestation information for Intel SGX enclaves.","properties":{"quote":{"type":"string","format":"byte","description":"Base-64 encoded SGX quote."},"endorsements":{"type":"string","format":"byte","description":"Base-64 encoded SGX endorsements."}},"required":["quote","endorsements"],"allOf":[{"$ref":"#/definitions/ServiceState.QuoteInfo"}],"x-ms-discriminator-value":"OE_SGX_v1"},"ServiceState.SnpJoinPolicy":{"type":"object","description":"Join policy fields specific to nodes running on AMD SEV-SNP hardware.","properties":{"measurements":{"type":"array","description":"Code measurements of acceptable enclaves.","items":{"type":"string","format":"byte"}},"hostData":{"type":"object","description":"Collection of acceptable host data values.","additionalProperties":{"format":"byte","type":"string"}},"uvmEndorsements":{"type":"object","description":"Collection of acceptable UVM endorsements.","additionalProperties":{"format":"byte","type":"string"}}},"required":["measurements","hostData","uvmEndorsements"]},"ServiceState.SnpQuoteInfo":{"type":"object","description":"Attestation information for AMD SEV-SNP containers.","properties":{"uvmEndorsements":{"type":"string","format":"byte","description":"Base-64 encoded SNP UVM endorsements."},"endorsedTcb":{"type":"string","format":"byte","description":"Base-64 encoded SNP TCB endorsements."}},"required":["uvmEndorsements","endorsedTcb"],"allOf":[{"$ref":"#/definitions/ServiceState.QuoteInfo"}],"x-ms-discriminator-value":"AMD_SEV_SNP_v1"},"ServiceState.caCertBundle":{"type":"string","description":"Chain of endorsed certificates (PEM format) leading to a CA."},"ServiceState.pem":{"type":"string","description":"PEM encoding of a cryptographic identifier. Contains a base64-encoded payload wrapped in content type identifiers."},"Transactions.CommittedTransaction":{"type":"object","description":"Description of latest committed transaction.","properties":{"transactionId":{"$ref":"#/definitions/transactionId","description":"Identifier of committed transaction."},"status":{"$ref":"#/definitions/Transactions.TransactionStatus","description":"Status of this transaction."}},"required":["transactionId","status"]},"Transactions.NamedTransaction":{"type":"object","description":"Description of a named transaction's current state.","properties":{"status":{"$ref":"#/definitions/Transactions.TransactionStatus","description":"Status of this transaction."}},"required":["status"]},"Transactions.Transaction":{"type":"object","description":"Common transaction information.","properties":{"status":{"$ref":"#/definitions/Transactions.TransactionStatus","description":"Status of this transaction."}},"required":["status"]},"Transactions.TransactionStatus":{"type":"string","description":"Possible states for a CCF transaction. See docs for details: https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#checking-for-commit","enum":["Unknown","Pending","Committed","Invalid"],"x-ms-enum":{"name":"TransactionStatus","modelAsString":true,"values":[{"name":"Unknown","value":"Unknown","description":"This is not a transaction the current node knows, but could exist in future. This may be returned when a transaction is created on one node then immediately queried on another, before it has been replicated."},{"name":"Pending","value":"Pending","description":"This transaction is known on the current node, but has not yet been committed. This is expected to be a temporary state."},{"name":"Committed","value":"Committed","description":"This transaction is known on the current node, and known to be committed. This means it has been replicated to a quorum of nodes, so will persist through future elections. Committed is a terminal state of this state machine."},{"name":"Invalid","value":"Invalid","description":"This transaction ID will never commit in the current service, because it contains a different term than a known transaction with the same sequence number. This can occur for a transaction ID returned from the service (ie - which was previously Unknown or Pending), if that transaction is lost during a consensus election. This should be rare. Invalid is a terminal state of this state machine."}]}},"Versions":{"type":"string","enum":["2023-06-01-preview"],"x-ms-enum":{"name":"Versions","modelAsString":true}},"memberId":{"type":"string","description":"Hex encoding of SHA-256 of a member certificate's fingerprint.","pattern":"^[a-f0-9]{64}$"},"nodeId":{"type":"string","description":"Hex encoding of SHA-256 of a node's public key.","pattern":"^[a-f0-9]{64}$"},"proposalId":{"type":"string","description":"Hex encoding of SHA-256 of proposed actions and merkle root of store at proposal creation. Unlike other IDs, this is generated on the service and will not be known in advance.","pattern":"^[a-f0-9]{64}$"},"safeuint":{"type":"integer","format":"int64","description":"A non-negative JSON-safe integer (ie max is 2^53 - 1)","minimum":0},"transactionId":{"type":"string","description":"Uniquely identifies an atomic transaction within a CCF service. Composed of a term number and sequence number. Sequence numbers increase monotonically, apart from during elections where the service may reuse an existing sequence number. Each election will result in a new, higher term number being used for the conflicting and future sequence numbers.","pattern":"^[0-9]+\\.[0-9]+$"},"userId":{"type":"string","description":"Hex encoding of SHA-256 of user certificate's fingerprint.","pattern":"^[a-f0-9]{64}$"}},"parameters":{"Azure.Core.Foundations.ApiVersionParameter":{"name":"api-version","in":"query","description":"The API version to use for this operation.","required":true,"type":"string","minLength":1,"x-ms-parameter-location":"method","x-ms-client-name":"apiVersion"},"CoseSignature.body":{"name":"body","in":"body","description":"A raw CoseSign1 signature. See CCF docs for required headers and body schema: https://microsoft.github.io/CCF/main/use_apps/issue_commands.html#cose-schemas","required":true,"schema":{"type":"string","format":"binary"},"x-ms-parameter-location":"method"}}} \ No newline at end of file From 6f7f34449e5f9eaa1151ba816cd6819b87fc329d Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 09:40:37 +0000 Subject: [PATCH 2/9] Handle that we now have a dir in the schema dir --- tests/schema.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/schema.py b/tests/schema.py index b84ccd56e4ad..56aa95d60fb7 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -22,9 +22,9 @@ def run(args): changed_files = [] old_schema = set( - os.path.join(dir_path, filename) - for dir_path, _, filenames in os.walk(args.schema_dir) - for filename in filenames + dir_entry.path + for dir_entry in os.scandir(args.schema_dir) + if dir_entry.is_file() ) documents_valid = True From 2ff3465813f1e2e8a7210cd8bfd279d30840258d Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 13:37:55 +0000 Subject: [PATCH 3/9] Replace use of classic API in docs --- doc/governance/accept_recovery.rst | 143 ++++++++++++-------- doc/governance/adding_member.rst | 41 ++++-- doc/governance/common_member_operations.rst | 93 ++++++------- doc/governance/hsm_keys.rst | 29 ++-- doc/governance/member_rpc_api.rst | 4 +- doc/governance/open_network.rst | 84 ++++++++---- doc/governance/proposals.rst | 140 ++++++++++++------- 7 files changed, 333 insertions(+), 201 deletions(-) diff --git a/doc/governance/accept_recovery.rst b/doc/governance/accept_recovery.rst index 689b560cce2b..cd024eedaebb 100644 --- a/doc/governance/accept_recovery.rst +++ b/doc/governance/accept_recovery.rst @@ -27,31 +27,57 @@ A member proposes to recover the network and other members can vote on the propo .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member1_privk.pem --signing-cert member1_cert.pem --content transition_service_to_open.json | \ - curl https:///gov/members/proposals:create?api-version=2023-06-01-preview --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at `date -uIs` \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + --content transition_service_to_open.json \ + | curl https:///gov/members/proposals:create?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 0, - "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", - "proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", - "state": "Open" + "ballotCount": 0, + "proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", + "proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", + "proposalState": "Open" } - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 --signing-key member1_privk.pem --signing-cert member1_cert.pem --content vote_accept.json | \ - curl https:///gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1:submit?api-version=2023-06-01-preview --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + --content vote_accept.json \ + | curl https:///gov/members/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 1, - "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", - "proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", - "state": "Open" + "ballotCount": 1, + "proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", + "proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", + "proposalState": "Open" } - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 --signing-key member2_privk.pem --signing-cert member2_cert.pem --content vote_accept.json | \ - curl https:///gov/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/e306e3a6eead2f4a3854302b41c3015bf12db9535ac0be1b8cf6584f84bca92b:submit?api-version=2023-06-01-preview --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id 1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377 \ + --signing-key member2_privk.pem \ + --signing-cert member2_cert.pem \ + --content vote_accept.json + | curl https:///gov/members/proposals/1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377/ballots/e306e3a6eead2f4a3854302b41c3015bf12db9535ac0be1b8cf6584f84bca92b:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 2, - "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", - "proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", - "state": "Accepted" + "ballotCount": 2, + "proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", + "proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", + "proposalState": "Accepted" } Once the proposal to recover the network has passed under the rules of the :term:`Constitution`, the recovered service is ready for members to submit their recovery shares. @@ -73,21 +99,29 @@ The recovery share retrieval, decryption and submission steps can be convenientl .. code-block:: bash - $ submit_recovery_share.sh https:// --member-enc-privk member0_enc_privk.pem --cert member0_cert.pem --api-version 2023-06-01-preview - --key member0_privk.pem --cacert service_cert.pem + $ submit_recovery_share.sh https:// \ + --member-enc-privk member0_enc_privk.pem \ + --cert member0_cert.pem \ + --api-version 2023-06-01-preview \ + --key member0_privk.pem \ + --cacert service_cert.pem HTTP/1.1 200 OK content-type: text/plain x-ms-ccf-transaction-id: 4.28 1/2 recovery shares successfully submitted. - $ submit_recovery_share.sh https:// --member-enc-privk member1_enc_privk.pem --cert member1_cert.pem --api-version 2023-06-01-preview - --key member1_privk.pem --cacert service_cert.pem + $ submit_recovery_share.sh https:// \ + --member-enc-privk member1_enc_privk.pem \ + --cert member1_cert.pem \ + --api-version 2023-06-01-preview \ + --key member1_privk.pem \ + --cacert service_cert.pem HTTP/1.1 200 OK content-type: text/plain x-ms-ccf-transaction-id: 4.30 2/2 recovery shares successfully submitted. End of recovery procedure initiated. -When the recovery threshold is reached, the :http:POST:`/gov/recovery_share` endpoint signals that the end of the recovery procedure is initiated and the that private ledger is now being recovered. Operators and members can monitor the progress of the private recovery process via the :http:GET:`/node/state` endpoint. +When the recovery threshold is reached, the :http:POST:`/gov/recovery/members/{memberId}:recover` response signals that the end of the recovery procedure is initiated and the that private ledger is now being recovered. Operators and members can monitor the progress of the private recovery process via the :http:GET:`/node/state` endpoint. .. note:: While all nodes are recovering the private ledger, no new transaction can be executed by the network. @@ -101,33 +135,36 @@ Summary Diagram .. mermaid:: sequenceDiagram - participant Member 0 - participant Member 1 - participant Users - participant Node 2 - participant Node 3 - - Note over Node 2, Node 3: Operators have restarted a public-only service - - Member 0->>+Node 2: Propose transition_service_to_open - Node 2-->>Member 0: Proposal ID - Member 1->>+Node 2: Vote for Proposal ID - Node 2-->>Member 1: State: Accepted - Note over Node 2, Node 3: transition_service_to_open proposal completes.
Service is ready to accept recovery shares. - - Member 0->>+Node 2: GET /gov/recovery/encrypted-shares/ - Node 2-->>Member 0: Encrypted recovery share for Member 0 - Note over Member 0: Decrypts recovery share - Member 0->>+Node 2: POST /gov/recovery/members/:recover": "" - Node 2-->>Member 0: 1/2 recovery shares successfully submitted. - - Member 1->>+Node 2: GET /gov/recovery/encrypted-shares/ - Node 2-->>Member 1: Encrypted recovery share for Member 1 - Note over Member 1: Decrypts recovery share - Member 1->>+Node 2: POST /gov/recovery/members/:recover": "" - Node 2-->>Member 1: End of recovery procedure initiated. - - Note over Node 2, Node 3: Reading Private Ledger... - - Note over Node 2: Recovery procedure complete - Note over Node 3: Recovery procedure complete + participant Member A + participant Member B + participant Node 0 + participant Node 1 + + Note over Node 0, Node 1: Operators have restarted a public-only service + + Member A->>+Node 0: Propose transition_service_to_open + Node 0-->>Member A: Proposal ID + Member B->>+Node 0: Vote for Proposal ID + Node 0-->>Member B: State: Accepted + + Note over Node 0: transition_service_to_open proposal completes.
Service is ready to accept recovery shares. + Node 0-->>Node 1: Replication + + Member A->>+Node 0: GET /gov/recovery/encrypted-shares/ + Node 0-->>Member A: Encrypted recovery share for Member A + Note over Member A: Decrypts recovery share + Member A->>+Node 0: POST /gov/recovery/members/:recover": "" + Node 0-->>Member A: 1/2 recovery shares successfully submitted. + + Member B->>+Node 0: GET /gov/recovery/encrypted-shares/ + Node 0-->>Member B: Encrypted recovery share for Member B + Note over Member B: Decrypts recovery share + Member B->>+Node 0: POST /gov/recovery/members/:recover": "" + Node 0-->>Member B: End of recovery procedure initiated. + + Note over Node 0: Reading Private Ledger... + Node 0-->>Node 1: Replication + Note over Node 1: Reading Private Ledger... + + Note over Node 0: Recovery procedure complete + Note over Node 1: Recovery procedure complete diff --git a/doc/governance/adding_member.rst b/doc/governance/adding_member.rst index 35ef16f532fd..e977fbc37c01 100644 --- a/doc/governance/adding_member.rst +++ b/doc/governance/adding_member.rst @@ -34,6 +34,7 @@ The CCF unique member identity is the hex-encoded string of the SHA-256 hash of $ identity_cert_path=/path/to/member/cert $ openssl x509 -in "$identity_cert_path" -noout -fingerprint -sha256 | cut -d "=" -f 2 | sed 's/://g' | awk '{print tolower($0)}' + 7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6 .. note:: See :ref:`architecture/cryptography:Algorithms and Curves` for the list of supported cryptographic curves for member identity. @@ -49,37 +50,47 @@ Activating a New Member A new member who gets registered in CCF is not yet able to participate in governance operations. To do so, the new member should first acknowledge that they are satisfied with the state of the service (for example, after auditing the current constitution and the nodes currently trusted). -First, the new member should update and retrieve the latest state digest via the :http:POST:`/gov/ack/update_state_digest` endpoint. In doing so, the new member confirms that they are satisfied with the current state of the service. +First, the new member should update and retrieve the latest state digest via the :http:POST:`/gov/members/state-digests/{memberId}:update` endpoint. In doing so, the new member confirms that they are satisfied with the current state of the service. .. code-block:: bash - $ curl https:///gov/ack/update_state_digest -X POST --cacert service_cert.pem --key new_member_privk.pem --cert new_member_cert.pem --silent | jq > request.json + $ curl https:///gov/members/state-digests/7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6:update?api-version=2023-06-01-preview \ + -X POST \ + --cacert service_cert.pem \ + --key new_member_privk.pem \ + --cert new_member_cert.pem \ + --silent | jq > request.json $ cat request.json { - "state_digest": <...> + "digest": <...> } -Then, the new member should sign the state digest returned by the :http:POST:`/gov/ack/update_state_digest` via the :http:POST:`/gov/ack` endpoint, using the ``ccf_cose_sign1`` utility: +Then, the new member should sign the state digest returned by :http:POST:`/gov/members/state-digests/{memberId}:update` (or :http:GET:`/gov/members/state-digests/{memberId}`) via the :http:POST:`/gov/members/state-digests/{memberId}:ack` endpoint, using the ``ccf_cose_sign1`` utility: .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type ack --ccf-gov-msg-created_at `date -uIs` --signing-key new_member_privk.pem --signing-cert new_member_cert.pem --content request.json | \ - curl https:///gov/ack --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" - true + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ack \ + --ccf-gov-msg-created_at `date -uIs` \ + --signing-key new_member_privk.pem \ + --signing-cert new_member_cert.pem \ + --content request.json \ + | curl https:///gov/members/state-digests/7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6:ack?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" -Once the command completes, the new member becomes active and can take part in governance operations (e.g. creating a new proposal or voting for an existing one). You can verify the activation of the member at `/gov/members`. +Once the command completes, the new member becomes active and can take part in governance operations (e.g. creating a new proposal or voting for an existing one). You can verify the activation of the member at :http:GET:`/gov/service/members/{memberId}`. .. code-block:: bash - $ curl https:///gov/members --silent | jq + $ curl https:///gov/service/members/7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6?api-version=2023-06-01-preview?api-version=2023-06-01-preview --silent | jq { - "": { - "cert": <...>, - "member_data": <...>, - "public_encryption_key": <...>, - "status": "Active" - } + "memberId": "7f46110b62ccbbd5f18b4c9bda876024399fd538133f8c26d4bfe5a9d80e59e6", + "certificate": <...>, + "memberData": <...>, + "status": "Active" } .. note:: The newly-activated member is also given a recovery share that can be used :ref:`to recover a defunct service `. diff --git a/doc/governance/common_member_operations.rst b/doc/governance/common_member_operations.rst index 6290f2ba78d6..d8e3d65a6afd 100644 --- a/doc/governance/common_member_operations.rst +++ b/doc/governance/common_member_operations.rst @@ -53,34 +53,60 @@ To limit the scope of key compromise, members of the consortium can refresh the .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member1_privk.pem --signing-cert member1_cert.pem --content trigger_ledger_rekey.json | \ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at `date -uIs` \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + --content trigger_ledger_rekey.json \ + | curl https:///gov/members/proposals:create?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 0, - "proposal_id": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" + "ballotCount": 0, + "proposalId": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Open" } - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e --signing-key member2_privk.pem --signing-cert member2_cert.pem --content vote_accept_1.json | \ - curl https:///gov/proposals/2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id 2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e \ + --signing-key member2_privk.pem \ + --signing-cert member2_cert.pem \ + --content vote_accept_1.json \ + | curl https:///gov/members/proposals/2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e/ballots/fe6ed012e8184f28afb48d0d58dca7f461dc997c43179acf97362dc0b76ddeb7:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 1, - "proposal_id": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" + "ballotCount": 1, + "proposalId": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Open" } - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id 2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e --signing-key member3_privk.pem --signing-cert member3_cert.pem --content vote_accept_1.json | \ - curl https:///gov/proposals/2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id 2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e \ + --signing-key member3_privk.pem \ + --signing-cert member3_cert.pem \ + --content vote_accept_1.json \ + | curl https:///gov/members/proposals/2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e/ballots/75b86775f1253c308f4e9aeddf912d40b8d77db9eaa9a0f0026f581920d5e9b8:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 2, - "proposal_id": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Accepted" + "ballotCount": 2, + "proposalId": "2f739d154b8cddacd7fc6d03cc8d4d20626e477ec4b1af10a74c670bb38bed5e", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Accepted" } -Once the proposal is accepted (``"state": "Accepted"``) it is immediately enacted. All subsequent transactions will be encrypted with a fresh new ledger encryption key. +Once the proposal is accepted (``"proposalState": "Accepted"``) it is immediately enacted. All subsequent transactions will be encrypted with a fresh new ledger encryption key. Updating Recovery Threshold --------------------------- @@ -105,35 +131,6 @@ The number of member shares required to restore the private ledger (``recovery_t ] } -.. code-block:: bash - - $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member1_privk.pem --signing-cert member1_cert.pem --content set_recovery_threshold.json | \ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" - { - "ballot_count": 0, - "proposal_id": "b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" - } - - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8 --signing-key member2_privk.pem --signing-cert member2_cert.pem --content vote_accept_1.json | \ - curl https:///gov/proposals/b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" - { - "ballot_count": 1, - "proposal_id": "b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" - } - - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8 --signing-key member3_privk.pem --signing-cert member3_cert.pem --content vote_accept_1.json | \ - curl https:///gov/proposals/b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" - { - "ballot_count": 2, - "proposal_id": "b9c08b3861395eca904d913427dcb436136e277cf4712eb14e9e9cddf9d231a8", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Accepted" - } - .. note:: The new recovery threshold has to be in the range between 1 and the current number of active recovery members. Renewing Node Certificate diff --git a/doc/governance/hsm_keys.rst b/doc/governance/hsm_keys.rst index de1ea938c6c1..5f5676cb7402 100644 --- a/doc/governance/hsm_keys.rst +++ b/doc/governance/hsm_keys.rst @@ -102,25 +102,38 @@ Finally, COSE Sign1 payload can be assembled with ``ccf_cose_sign1_finish``: .. code-block:: bash - $ ccf_cose_sign1_finish --ccf-gov-msg-type proposal --ccf-gov-msg-created_at $CREATED_AT --content proposal.json --signing-cert $IDENTITY_CERT_NAME.pem --signature signature > cose_sign1 + $ ccf_cose_sign1_finish \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at $CREATED_AT \ + --content proposal.json \ + --signing-cert $IDENTITY_CERT_NAME.pem \ + --signature signature > cose_sign1 Like ``ccf_cose_sign1``, the output can be sent directly to the service via curl: .. code-block:: bash - $ ccf_cose_sign1_finish --ccf-gov-msg-type proposal --ccf-gov-msg-created_at $CREATED_AT --content proposal.json --signing-cert $IDENTITY_CERT_NAME.pem --signature |\ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1_finish \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at $CREATED_AT \ + --content proposal.json \ + --signing-cert $IDENTITY_CERT_NAME.pem \ + --signature signature \ + | curl https:///gov/members/proposals:create?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 0, - "proposal_id": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", - "proposer_id": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", - "state": "Open" + "ballotCount": 0, + "proposalId": "1b7cae1585077104e99e1860ad740efe28ebd498dbf9988e0e7b299e720c5377", + "proposerId": "d5d7d5fed6f839028456641ad5c3df18ce963bd329bd8a21df16ccdbdbba1eb1", + "proposalState": "Open" } Recovery Share Decryption ------------------------- -A member can fetch their encrypted recovery share through :http:GET:`/gov/encrypted_recovery_share/{member_id}` (see :ref:`governance/accept_recovery:Submitting Recovery Shares`). +A member can fetch their encrypted recovery share through :http:GET:`/gov/recovery/encrypted-shares/{memberId}` (see :ref:`governance/accept_recovery:Submitting Recovery Shares`). The retrieved encrypted recovery share can be decrypted with the encryption key stored in Key Vault: diff --git a/doc/governance/member_rpc_api.rst b/doc/governance/member_rpc_api.rst index 2e8a410b57b4..249d870d025d 100644 --- a/doc/governance/member_rpc_api.rst +++ b/doc/governance/member_rpc_api.rst @@ -1,9 +1,9 @@ Member RPC API ============== -Member RPCs are exposed under ``/gov``. Many require COSE authentication, with the payload signed by a member identity. Others provide public read access to governance state. +Member RPCs are exposed under the ``/gov`` prefix. Many require COSE authentication, with the payload signed by a member identity. Others provide public read access to governance state. -# TODO: The following is the old, deprecated API +Multiple API versions are available, with the versions supported by the current CCF version listed below: .. toctree:: diff --git a/doc/governance/open_network.rst b/doc/governance/open_network.rst index c9385c0400fe..51c1d9721e7e 100644 --- a/doc/governance/open_network.rst +++ b/doc/governance/open_network.rst @@ -1,7 +1,7 @@ Opening a Network ================= -This sections assumes that a set of nodes has already been started by :term:`Operators`. See :doc:`/operations/start_network`. +This section assumes that a set of nodes has already been started by :term:`Operators`. See :doc:`/operations/start_network`. Adding Users @@ -27,13 +27,21 @@ Then, the certificates of trusted users should be registered in CCF via the memb .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member0_privk.pem --signing-cert member0_cert.pem --content set_user.json | \ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at `date -uIs` \ + --signing-key member0_privk.pem \ + --signing-cert member0_cert.pem \ + --content set_user.json \ + | curl https:///gov/members/proposals:create?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 0, - "proposal_id": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" + "ballotCount": 0, + "proposalId": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Open" } Other members are then allowed to vote for the proposal, using the proposal id returned to the proposer member. They may submit an unconditional approval, or their vote may query the current state and the proposed actions. These votes `must` be signed. @@ -47,24 +55,42 @@ Other members are then allowed to vote for the proposal, using the proposal id r .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253 --signing-key member0_privk.pem --signing-cert member0_cert.pem --content vote_accept.json | \ - curl https:///gov/f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253 \ + --signing-key member0_privk.pem \ + --signing-cert member0_cert.pem \ + --content vote_accept.json \ + | curl https:///gov/members/proposals/f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253/ballots/2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 1, - "proposal_id": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" + "ballotCount": 1, + "proposalId": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Open" } .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253 --signing-key member0_privk.pem --signing-cert member0_cert.pem --content vote_conditional.json | \ - curl https:///gov/f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253 \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + --content vote_accept.json \ + | curl https:///gov/members/proposals/f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253/ballots/75b86775f1253c308f4e9aeddf912d40b8d77db9eaa9a0f0026f581920d5e9b8:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 2, - "proposal_id": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Accepted" + "ballotCount": 2, + "proposalId": "f665047e3d1eb184a7b7921944a8ab543cfff117aab5b6358dc87f9e70278253", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Open" } The user is successfully added once the proposal has received enough votes under the rules of the :term:`Constitution` (indicated by the response body showing a transition to state ``Accepted``). @@ -143,13 +169,21 @@ Once users are added to the opening network, members should create a proposal to .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member0_privk.pem --signing-cert member0_cert.pem --content transition_service_to_open.json | \ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at `date -uIs` \ + --signing-key member0_privk.pem \ + --signing-cert member0_cert.pem \ + --content transition_service_to_open.json + | curl https:///gov/members/proposals:create?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 0, - "proposal_id": "77374e16de0b2d61f58aec84d01e6218205d19c9401d2df127d893ce62576b81", - "proposer_id": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", - "state": "Open" + "ballotCount": 0, + "proposalId": "77374e16de0b2d61f58aec84d01e6218205d19c9401d2df127d893ce62576b81", + "proposerId": "2af6cb6c0af07818186f7ef7151061174c3cb74b4a4c30a04a434f0c2b00a8c0", + "proposalState": "Open" } Other members are then able to vote for the proposal using the returned proposal id. diff --git a/doc/governance/proposals.rst b/doc/governance/proposals.rst index df48b59ebe99..bc3a48e51ba1 100644 --- a/doc/governance/proposals.rst +++ b/doc/governance/proposals.rst @@ -27,14 +27,14 @@ For transparency and auditability, all governance operations (including votes) a participant Constitution Note over MemberFrontend, Constitution: CCF - Member 0->>+MemberFrontend: Submit Proposal to /gov/proposals + Member 0->>+MemberFrontend: Submit Proposal to /gov/members/proposals:create MemberFrontend->>+Constitution: call validate(Proposal) Constitution-->>-MemberFrontend: no exception MemberFrontend->>+Constitution: call resolve(Proposal, {}) Constitution-->>-MemberFrontend: not enough votes, return Proposal is Open MemberFrontend-->>-Member 0: Proposal is Open - Member 1->>+MemberFrontend: Submit Ballot containing vote() to /gov/proposals/ProposalID/ballots + Member 1->>+MemberFrontend: Submit Ballot containing vote() MemberFrontend->>MemberFrontend: evaluate vote(Proposal, KV State) to boolean Vote MemberFrontend->>+Constitution: call resolve(Proposal, {Member 1: Vote}) Constitution-->>-MemberFrontend: enough positive votes, return Proposal is Accepted @@ -251,7 +251,7 @@ These proposals and votes should be sent as the body of HTTP requests as describ Submitting a New Proposal ------------------------- -Assuming that 3 members (``member1``, ``member2`` and ``member3``) are already registered in the CCF network and that the sample constitution is used, a member can submit a new proposal using :http:POST:`/gov/proposals` and vote using :http:POST:`/gov/proposals/{proposal_id}/ballots`. +Assuming that 3 members (``member1``, ``member2`` and ``member3``) are already registered in the CCF network and that the sample constitution is used, a member can submit a new proposal using :http:POST:`/gov/members/proposals:create` and vote using :http:POST:`/gov/members/proposals/{proposalId}/ballots/{memberId}:submit`. For example, ``member1`` may submit a proposal to add a new member (``member4``) to the consortium: @@ -272,16 +272,24 @@ For example, ``member1`` may submit a proposal to add a new member (``member4``) .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type proposal --ccf-gov-msg-created_at `date -uIs` --signing-key member1_privk.pem --signing-cert member1_cert.pem --content add_member.json | \ - curl https:///gov/proposals --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type proposal \ + --ccf-gov-msg-created_at `date -uIs` \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + --content add_member.json \ + | curl https:///gov/members/proposals:create?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 0, - "proposal_id": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", - "proposer_id": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", - "state": "Open" + "ballotCount": 0, + "proposalId": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", + "proposerId": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", + "proposalState": "Open" } -Here a new proposal has successfully been created, and nobody has yet voted for it. The proposal is in state ``Open``, meaning it will can receive additional votes. Members can then vote to accept or reject the proposal: +Here a new proposal has successfully been created, and nobody has yet voted for it. The proposal is in state ``Open``, meaning it can receive additional votes. Members can then vote to accept or reject the proposal: .. code-block:: bash @@ -298,78 +306,110 @@ Here a new proposal has successfully been created, and nobody has yet voted for .. code-block:: bash # Member 1 approves the proposal (votes in favour: 1/3) - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd --signing-key member1_privk.pem --signing-cert member1_cert.pem --content vote_accept.json | \ - curl https:///gov/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + --content vote_accept.json \ + | curl https:///gov/members/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/ballots/52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 1, - "proposal_id": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", - "proposer_id": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", - "state": "Open" + "ballotCount": 1, + "proposalId": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", + "proposerId": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", + "proposalState": "Open" } - # Member 2 approves the proposal (votes in favour: 1/3) - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd --signing-key member2_privk.pem --signing-cert member2_cert.pem --content vote_reject.json | \ - curl https:///gov/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + # Member 2 rejects the proposal (votes in favour: 1/3) + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd \ + --signing-key member2_privk.pem \ + --signing-cert member2_cert.pem \ + --content vote_reject.json \ + | curl https:///gov/members/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/ballots/fe6ed012e8184f28afb48d0d58dca7f461dc997c43179acf97362dc0b76ddeb7:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 2, - "proposal_id": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", - "proposer_id": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", - "state": "Open" + "ballotCount": 2, + "proposalId": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", + "proposerId": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", + "proposalState": "Open" } # Member 3 approves the proposal (votes in favour: 2/3) - $ ccf_cose_sign1 --ccf-gov-msg-type ballot --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd --signing-key member3_privk.pem --signing-cert member3_cert.pem --content vote_accept.json | \ - curl https:///gov/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/ballots --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type ballot \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd \ + --signing-key member3_privk.pem \ + --signing-cert member3_cert.pem \ + --content vote_accept.json \ + | curl https:///gov/members/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/ballots/75b86775f1253c308f4e9aeddf912d40b8d77db9eaa9a0f0026f581920d5e9b8:submit?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 3, - "proposal_id": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", - "proposer_id": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", - "state": "Accepted" + "ballotCount": 3, + "proposalId": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", + "proposerId": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", + "proposalState": "Accepted" } # As a majority of members have accepted the proposal, member 4 is added to the consortium As soon as ``member3`` accepts the proposal, a majority (2 out of 3) of members has been reached and the proposal completes, successfully adding ``member4``. The response shows this, as the proposal's state is now ``Accepted``. -.. note:: Once a new member has been accepted to the consortium, the new member must acknowledge that it is active by sending a :http:POST:`/gov/ack` request. See :ref:`governance/adding_member:Activating a New Member`. +.. note:: Once a new member has been accepted to the consortium, the new member must acknowledge that it is active by sending a :http:POST:`/gov/members/state-digests/{memberId}:ack` request. See :ref:`governance/adding_member:Activating a New Member`. Displaying Proposals -------------------- -The details of pending proposals, can be queried from the service by calling :http:GET:`/gov/proposals/{proposal_id}`. For example, after accepting the proposal above: +The details of pending proposals, can be queried from the service by calling :http:GET:`/gov/members/proposals/{proposalId}`. For example, after accepting the proposal above: .. code-block:: bash - $ curl https:///gov/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd --cacert service_cert.pem -X GET + $ curl https:///gov/members/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd?api-version=2023-06-01-preview --cacert service_cert.pem -X GET { - "ballots": { - "0d8866bf4623a685963f3c087cd6fdcdf48fc483d774f7fc28bf428e31755aaa": "export function vote (proposal, proposerId) { return true }", - "466cc43f0cd17df4b49ded4b833f7bbba43b15ebee5be896d91e823fcce96a69": "export function vote (proposal, proposerId) { return true }", - "fe1b9b511fb3cf3ca3a1289b0d44db83a80dee8a54492f29467c52ebef9dbe40": "export function vote (proposal, proposerId) { return false }" + "ballotCount": 3, + "finalVotes": { + "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73": true, + "75b86775f1253c308f4e9aeddf912d40b8d77db9eaa9a0f0026f581920d5e9b8": true, + "fe6ed012e8184f28afb48d0d58dca7f461dc997c43179acf97362dc0b76ddeb7": false }, - "final_votes": { - "0d8866bf4623a685963f3c087cd6fdcdf48fc483d774f7fc28bf428e31755aaa": true, - "466cc43f0cd17df4b49ded4b833f7bbba43b15ebee5be896d91e823fcce96a69": true, - "fe1b9b511fb3cf3ca3a1289b0d44db83a80dee8a54492f29467c52ebef9dbe40": false - }, - "proposer_id": "0d8866bf4623a685963f3c087cd6fdcdf48fc483d774f7fc28bf428e31755aaa", - "state": "Accepted" + "proposalId": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", + "proposerId": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", + "proposalState": "Accepted" } Withdrawing a Proposal ---------------------- -At any stage during the voting process, before the proposal is accepted, the proposing member may decide to withdraw a pending proposal: +At any stage during the voting process, before the proposal is accepted, the proposing member may unanimously withdraw a proposal by calling :http:POST:`/gov/members/proposals/{proposalId}:withdraw`: .. code-block:: bash - $ ccf_cose_sign1 --ccf-gov-msg-type withdrawal --ccf-gov-msg-created_at `date -uIs` --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd --signing-key member1_privk.pem --signing-cert member1_cert.pem | \ - curl https:///gov/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd/withdraw --cacert service_cert.pem --data-binary @- -H "content-type: application/cose" + $ ccf_cose_sign1 \ + --ccf-gov-msg-type withdrawal \ + --ccf-gov-msg-created_at `date -uIs` \ + --ccf-gov-msg-proposal_id d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd \ + --signing-key member1_privk.pem \ + --signing-cert member1_cert.pem \ + | curl https:///gov/members/proposals/d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd:withdraw?api-version=2023-06-01-preview \ + --cacert service_cert.pem \ + --data-binary @- \ + -H "content-type: application/cose" { - "ballot_count": 1, - "proposal_id": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", - "proposer_id": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", - "state": "Withdrawn" + "ballotCount": 1, + "proposalId": "d4ec2de82267f97d3d1b464020af0bd3241f1bedf769f0fee73cd00f08e9c7fd", + "proposerId": "52af2620fa1b005a93d55d7d819a249ee2cb79f5262f54e8db794c5281a0ce73", + "proposlState": "Withdrawn" } This means future votes will be rejected, and the proposal will never be accepted. However it remains visible as a proposal so members can easily audit historic proposals. From dbc1b8dd40f8d9d6fe72536086fbf2cc46a286ab Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 13:38:06 +0000 Subject: [PATCH 4/9] Add guide on upgrading from classic API --- doc/governance/gov_api_schemas/classic.rst | 13 +- .../upgrading_from_classic.rst | 251 ++++++++++++++++++ 2 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 doc/governance/gov_api_schemas/upgrading_from_classic.rst diff --git a/doc/governance/gov_api_schemas/classic.rst b/doc/governance/gov_api_schemas/classic.rst index 1df19b8fd8f6..fc8f46990a67 100644 --- a/doc/governance/gov_api_schemas/classic.rst +++ b/doc/governance/gov_api_schemas/classic.rst @@ -1,9 +1,16 @@ Classic API =========== -Available in CCF versions before v5.0.0. +Available in CCF versions before 5.0.0. -.. warning:: This API is deprecated, and will be removed in a future release. Use a more recent version. +Any request calling a path with a ``/gov`` prefix which does not include the ``api-version`` query parameter is calling the classic API. + +.. warning:: This API is deprecated, and will be removed in a future release. See :doc:`/governance/gov_api_schemas/upgrading_from_classic` for a guide to upgrading to a more recent version. .. openapi:: ../../schemas/gov_openapi.json - :examples: \ No newline at end of file + :examples: + +.. toctree:: + :hidden: + + upgrading_from_classic \ No newline at end of file diff --git a/doc/governance/gov_api_schemas/upgrading_from_classic.rst b/doc/governance/gov_api_schemas/upgrading_from_classic.rst new file mode 100644 index 000000000000..f247649db5c0 --- /dev/null +++ b/doc/governance/gov_api_schemas/upgrading_from_classic.rst @@ -0,0 +1,251 @@ +Upgrading From Classic API +========================== + +Earlier versions of CCF exposed an alternative governance API, now known as the "classic API". The bulk of the endpoints from the classic API have a direct replacement in the new API, as laid out below. Note that the response format may not match exactly. For instance response fields in JSON objects will be ``camelCase`` rather than ``snake_case``, and list responses may now be paged. See the API schema for the new version for a precise description of the response format of each request. + +Note that all new APIs require the ``api-version`` query parameter to be set, and will return an error if called without this parameter, or when its value does not match a known API version. + +Proposals +--------- + +.. list-table:: + :align: left + + * - Purpose + - Create a new proposal + * - Classic + - :http:POST:`/gov/proposals` + * - Replacement + - :http:POST:`/gov/members/proposals:create` + +.. list-table:: + :align: left + + * - Purpose + - Get single proposal + * - Classic + - :http:GET:`/gov/proposals/{proposal_id}` + * - Replacement + - :http:GET:`/gov/members/proposals/{proposalId}` + +.. list-table:: + :align: left + + * - Purpose + - Get all proposals + * - Classic + - :http:GET:`/gov/proposals` + * - Replacement + - :http:GET:`/gov/members/proposals` + +.. list-table:: + :align: left + + * - Purpose + - Get actions of proposal + * - Classic + - :http:GET:`/gov/proposals/{proposal_id}/actions` + * - Replacement + - :http:GET:`/gov/members/proposals/{proposalId}/actions` + +.. list-table:: + :align: left + + * - Purpose + - Withdraw a proposal + * - Classic + - :http:POST:`/gov/proposals/{proposal_id}/withdraw` + * - Replacement + - :http:POST:`/gov/members/proposals/{proposalId}:withdraw` + +Ballots +------- + +.. list-table:: + :align: left + + * - Purpose + - Submit a ballot + * - Classic + - :http:POST:`/gov/proposals/{proposal_id}/ballots` + * - Replacement + - :http:POST:`/gov/members/proposals/{proposalId}/ballots/{memberId}:submit` + +.. list-table:: + :align: left + + * - Purpose + - Get a ballot + * - Classic + - :http:GET:`/gov/proposals/{proposal_id}/ballots/{member_id}` + * - Replacement + - :http:GET:`/gov/members/proposals/{proposalId}/ballots/{memberId}` + +Member Activation +----------------- + +.. list-table:: + :align: left + + * - Purpose + - Get a fresh state-digest to ACK + * - Classic + - :http:POST:`/gov/ack/update_state_digest` + * - Replacement + - :http:POST:`/gov/members/state-digests/{memberId}:update` + * - Notes + - Can also retrieve without refreshing, with :http:GET:`/gov/members/state-digests/{memberId}` + +.. list-table:: + :align: left + + * - Purpose + - Submit signed ACK + * - Classic + - :http:POST:`/gov/ack` + * - Replacement + - :http:POST:`/gov/members/state-digests/{memberId}:ack` + +Transaction Status +------------------ + +.. list-table:: + :align: left + + * - Purpose + - Get status of single transaction + * - Classic + - :http:GET:`/gov/tx` + * - Replacement + - :http:GET:`/gov/service/transactions/{transactionId}` + * - Notes + - Transaction ID has moved from query parameter to path parameter. + +.. list-table:: + :align: left + + * - Purpose + - Get latest committed transaction + * - Classic + - :http:GET:`/gov/commit` + * - Replacement + - :http:GET:`/gov/service/transactions/commit` + +.. note:: ``/node/tx`` and ``/node/commit`` remain available in the old style, for existing operator code. + +Recovery +-------- + +.. list-table:: + :align: left + + * - Purpose + - Get encrypted recovery share for a member + * - Classic + - :http:GET:`/gov/recovery_share` + * - Replacement + - :http:GET:`/gov/recovery/encrypted-shares/{memberId}` + * - Notes + - | The new endpoint is unauthenticated and takes the target member ID as a path parameter, where the Classic API required authentication as a member. + | Since shares are encrypted, they can be safely read by anyone, without authentication. + +.. list-table:: + :align: left + + * - Purpose + - Submit signed recovery share to advance recovery + * - Classic + - :http:POST:`/gov/recovery_share` + * - Replacement + - :http:POST:`/gov/recovery/members/{memberId}:recover` + +Service State +------------- + +.. list-table:: + :align: left + + * - Purpose + - Read details of currently service identity and recovery status + * - Classic + - :http:GET:`/gov/kv/service/info` + * - Replacement + - :http:GET:`/gov/service/info` + +.. list-table:: + :align: left + + * - Purpose + - Read current constitution + * - Classic + - :http:GET:`/gov/kv/constitution` + * - Replacement + - :http:GET:`/gov/service/constitution` + * - Notes + - The new endpoint returns a ``Content-Type: text/javascript`` response containing the raw constitution, rather than encoding it within a JSON value. + +.. list-table:: + :align: left + + * - Purpose + - Read list of current members + * - Classic + - | :http:GET:`/gov/kv/members/certs` + | :http:GET:`/gov/kv/members/info` + | :http:GET:`/gov/kv/members/encryption_public_keys` + * - Replacement + - :http:GET:`/gov/service/members` + * - Notes + - | Single endpoint replaces multiple previous endpoints. + | Entry for single member is also available at :http:GET:`/gov/service/members/{memberId}`. + +.. list-table:: + :align: left + + * - Purpose + - Read list of current nodes + * - Classic + - | :http:GET:`/gov/kv/nodes/endorsed_certificates` + | :http:GET:`/gov/kv/nodes/info` + * - Replacement + - :http:GET:`/gov/service/nodes` + * - Notes + - | Single endpoint replaces multiple previous endpoints. + | Entry for single node is also available at :http:GET:`/gov/service/nodes/{nodeId}`. + +.. list-table:: + :align: left + + * - Purpose + - Establish what attestations are required for a new node to join the service + * - Classic + - | :http:GET:`/gov/kv/nodes/code_ids` + | :http:GET:`/gov/kv/nodes/snp/host_data` + | :http:GET:`/gov/kv/nodes/snp/uvm_endorsements` + * - Replacement + - :http:GET:`/gov/service/join-policy` + * - Notes + - | Single endpoint replaces multiple previous endpoints. + +.. list-table:: + :align: left + + * - Purpose + - Read details of currently deployed JavaScript app + * - Classic + - :http:GET:`/gov/kv/modules` + * - Replacement + - :http:GET:`/gov/service/javascript-app` + +.. list-table:: + :align: left + + * - Purpose + - Read details of accepted JWKs and their issuers + * - Classic + - | :http:GET:`/gov/kv/jwt/issuers` + | :http:GET:`/gov/kv/jwt/public_signing_keys` + * - Replacement + - :http:GET:`/gov/service/jwk` + * - Notes + - | Single endpoint replaces multiple previous endpoints. \ No newline at end of file From a74921ec436b0926e6c1afbedd3594db95537fe2 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 13:41:04 +0000 Subject: [PATCH 5/9] Mention upgrade guide in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19d82e5fb5a9..b8db9730c87c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [5.0.0-dev3]: https://github.com/microsoft/CCF/releases/tag/ccf-5.0.0-dev3 - Added a `consensus.max_uncommitted_tx_count` configuration option, which specifies the maximum number of transactions that can be pending on the primary. When that threshold is exceeded, a `503 Service Unavailable` is temporarily returned on all but the `/node/*` paths (#5692). -- A new versioned governance API is now available, with the `api-version=2023-06-01-preview` query parameter. This will fully replace the previous governance endpoints, which will be removed in a future release. +- A new versioned governance API is now available, with the `api-version=2023-06-01-preview` query parameter. This will fully replace the previous governance endpoints, which will be removed in a future release. A guide to aid in upgrading from the previous API is available [here](https://microsoft.github.io/CCF/main/governance/gov_api_schemas/upgrading_from_classic.html) ## [5.0.0-dev2] From 04404334a36cb9f265f792b253c2227fdf449933 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 13:41:53 +0000 Subject: [PATCH 6/9] Move upgrading docs up one level --- doc/governance/gov_api_schemas/classic.rst | 5 ----- doc/governance/member_rpc_api.rst | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/governance/gov_api_schemas/classic.rst b/doc/governance/gov_api_schemas/classic.rst index fc8f46990a67..490497171b20 100644 --- a/doc/governance/gov_api_schemas/classic.rst +++ b/doc/governance/gov_api_schemas/classic.rst @@ -9,8 +9,3 @@ Any request calling a path with a ``/gov`` prefix which does not include the ``a .. openapi:: ../../schemas/gov_openapi.json :examples: - -.. toctree:: - :hidden: - - upgrading_from_classic \ No newline at end of file diff --git a/doc/governance/member_rpc_api.rst b/doc/governance/member_rpc_api.rst index 249d870d025d..8da0754bd824 100644 --- a/doc/governance/member_rpc_api.rst +++ b/doc/governance/member_rpc_api.rst @@ -9,3 +9,4 @@ Multiple API versions are available, with the versions supported by the current gov_api_schemas/2023-06-01-preview gov_api_schemas/classic + gov_api_schemas/upgrading_from_classic From 34033ae7a4c55f99f59aab50421740e6c5be4793 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 15:39:28 +0100 Subject: [PATCH 7/9] Update doc/governance/accept_recovery.rst Co-authored-by: Amaury Chamayou --- doc/governance/accept_recovery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/governance/accept_recovery.rst b/doc/governance/accept_recovery.rst index cd024eedaebb..8287788357e3 100644 --- a/doc/governance/accept_recovery.rst +++ b/doc/governance/accept_recovery.rst @@ -121,7 +121,7 @@ The recovery share retrieval, decryption and submission steps can be convenientl x-ms-ccf-transaction-id: 4.30 2/2 recovery shares successfully submitted. End of recovery procedure initiated. -When the recovery threshold is reached, the :http:POST:`/gov/recovery/members/{memberId}:recover` response signals that the end of the recovery procedure is initiated and the that private ledger is now being recovered. Operators and members can monitor the progress of the private recovery process via the :http:GET:`/node/state` endpoint. +When the recovery threshold is reached, the :http:POST:`/gov/recovery/members/{memberId}:recover` response signals that the end of the recovery procedure is initiated and that the private ledger is now being recovered. Operators and members can monitor the progress of the private recovery process via the :http:GET:`/node/state` endpoint. .. note:: While all nodes are recovering the private ledger, no new transaction can be executed by the network. From 67350bc1a3844c94bd3b636d7ec33cd5c378cb04 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 14:41:56 +0000 Subject: [PATCH 8/9] Review feedback --- doc/governance/accept_recovery.rst | 40 ++++++++----------- .../gov_api_schemas/2023-06-01-preview.rst | 5 ++- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/doc/governance/accept_recovery.rst b/doc/governance/accept_recovery.rst index cd024eedaebb..2f222b2f6351 100644 --- a/doc/governance/accept_recovery.rst +++ b/doc/governance/accept_recovery.rst @@ -137,34 +137,28 @@ Summary Diagram sequenceDiagram participant Member A participant Member B - participant Node 0 - participant Node 1 + participant Network - Note over Node 0, Node 1: Operators have restarted a public-only service + Note over Network: Operators have restarted a public-only service - Member A->>+Node 0: Propose transition_service_to_open - Node 0-->>Member A: Proposal ID - Member B->>+Node 0: Vote for Proposal ID - Node 0-->>Member B: State: Accepted + Member A->>+Network: Propose transition_service_to_open + Network-->>Member A: Proposal ID + Member B->>+Network: Vote for Proposal ID + Network-->>Member B: State: Accepted - Note over Node 0: transition_service_to_open proposal completes.
Service is ready to accept recovery shares. - Node 0-->>Node 1: Replication + Note over Network: transition_service_to_open proposal completes.
Service is ready to accept recovery shares. - Member A->>+Node 0: GET /gov/recovery/encrypted-shares/ - Node 0-->>Member A: Encrypted recovery share for Member A + Member A->>+Network: GET /gov/recovery/encrypted-shares/ + Network-->>Member A: Encrypted recovery share for Member A Note over Member A: Decrypts recovery share - Member A->>+Node 0: POST /gov/recovery/members/:recover": "" - Node 0-->>Member A: 1/2 recovery shares successfully submitted. + Member A->>+Network: POST /gov/recovery/members/:recover": "" + Network-->>Member A: 1/2 recovery shares successfully submitted. - Member B->>+Node 0: GET /gov/recovery/encrypted-shares/ - Node 0-->>Member B: Encrypted recovery share for Member B + Member B->>+Network: GET /gov/recovery/encrypted-shares/ + Network-->>Member B: Encrypted recovery share for Member B Note over Member B: Decrypts recovery share - Member B->>+Node 0: POST /gov/recovery/members/:recover": "" - Node 0-->>Member B: End of recovery procedure initiated. + Member B->>+Network: POST /gov/recovery/members/:recover": "" + Network-->>Member B: End of recovery procedure initiated. - Note over Node 0: Reading Private Ledger... - Node 0-->>Node 1: Replication - Note over Node 1: Reading Private Ledger... - - Note over Node 0: Recovery procedure complete - Note over Node 1: Recovery procedure complete + Note over Network: Reading Private Ledger... + Note over Network: Recovery procedure complete diff --git a/doc/governance/gov_api_schemas/2023-06-01-preview.rst b/doc/governance/gov_api_schemas/2023-06-01-preview.rst index 34cccca1ee46..be652560ed04 100644 --- a/doc/governance/gov_api_schemas/2023-06-01-preview.rst +++ b/doc/governance/gov_api_schemas/2023-06-01-preview.rst @@ -3,6 +3,7 @@ This API is available by passing the query parameter ``api-version=2023-06-01-preview`` to endpoints under the ``/gov`` prefix. -This is available from CCF 5.0.0. +This is available from CCF 5.0.0-dev3. -.. openapi:: ../../schemas/mccf/2023-06-01-preview/mccfgov.json \ No newline at end of file +.. openapi:: ../../schemas/mccf/2023-06-01-preview/mccfgov.json + \ No newline at end of file From af7dd274633f3ffe7c2ece5939262a05e470ec70 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Fri, 6 Oct 2023 16:11:11 +0100 Subject: [PATCH 9/9] Update doc/governance/proposals.rst Co-authored-by: Amaury Chamayou --- doc/governance/proposals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/governance/proposals.rst b/doc/governance/proposals.rst index bc3a48e51ba1..0cb02da34a26 100644 --- a/doc/governance/proposals.rst +++ b/doc/governance/proposals.rst @@ -391,7 +391,7 @@ The details of pending proposals, can be queried from the service by calling :ht Withdrawing a Proposal ---------------------- -At any stage during the voting process, before the proposal is accepted, the proposing member may unanimously withdraw a proposal by calling :http:POST:`/gov/members/proposals/{proposalId}:withdraw`: +At any stage during the voting process, before the proposal is accepted, the proposing member may unilaterally withdraw a proposal by calling :http:POST:`/gov/members/proposals/{proposalId}:withdraw`: .. code-block:: bash