diff --git a/docs/openapi/convey-clients.json b/docs/openapi/convey-clients.json index 5be77e7ce..abd92f063 100644 --- a/docs/openapi/convey-clients.json +++ b/docs/openapi/convey-clients.json @@ -8302,7 +8302,8 @@ "application/json": { "example": { "device_label": "Jer iPhone", - "role": "phone" + "role": "phone", + "same_machine": false }, "schema": { "additionalProperties": true, @@ -8312,6 +8313,9 @@ }, "role": { "type": "string" + }, + "same_machine": { + "type": "boolean" } }, "type": "object" @@ -8384,8 +8388,9 @@ } } }, - "description": "Access gate rejected a revoked paired-link identity.", + "description": "Access gate rejected the pair-start request.", "x-reason-codes": [ + "local_request_only", "pl_revoked" ] }, @@ -8573,23 +8578,49 @@ "content": { "application/json": { "example": { + "revoked_observers": [ + { + "name": "phone-a", + "prefix": "phone-a-" + } + ], "unpaired": "sha256:abc123" }, "schema": { "additionalProperties": true, "properties": { + "revoked_observers": { + "items": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "prefix": { + "type": "string" + } + }, + "required": [ + "name", + "prefix" + ], + "type": "object" + }, + "type": "array" + }, "unpaired": { "type": "string" } }, "required": [ - "unpaired" + "unpaired", + "revoked_observers" ], "type": "object" } } }, - "description": "The revoked fingerprint." + "description": "The revoked fingerprint and any observer records revoked with it." }, "400": { "content": { @@ -8629,6 +8660,19 @@ "x-reason-codes": [ "paired_device_not_found" ] + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + }, + "description": "Observer revoke cascade failed after the device was unpaired.", + "x-reason-codes": [ + "internal_error" + ] } }, "summary": "Unpair a device", diff --git a/docs/openapi/observer-client-contract/manifest.json b/docs/openapi/observer-client-contract/manifest.json index 7a851435b..7d7190805 100644 --- a/docs/openapi/observer-client-contract/manifest.json +++ b/docs/openapi/observer-client-contract/manifest.json @@ -14,7 +14,7 @@ } ], "bundle_schema_identity": "solstone.observer-client-contract-bundle.schema.v1", - "bundle_semver": "5.0.5", + "bundle_semver": "5.0.6", "component_closure": [ "CallosumEvent", "Error", @@ -55,7 +55,7 @@ "id": "bundle.projection_builder", "path": "solstone/convey/contract/observer_bundle.py", "role": "projection_builder", - "sha256": "0396a1e5a87b34ea67ec6e4bb2e5272821ecd85bd3367d078e81a24b05db6f21" + "sha256": "6ef92c49cbc70afa532497151c2b1e0f95d59cd364cdc95df8a66c9e36eabbb2" }, { "id": "bundle.recording", @@ -85,7 +85,7 @@ "id": "fragment.link", "path": "solstone/apps/network/contract.py", "role": "code_adjacent_fragment", - "sha256": "d5c11897d4690cbf591b71a99ddaa4bbfd6631f154974d3f71090cb695626b80" + "sha256": "937e8bd824ba40117e6d64656b3fdb54b9e768659346865146791a97a6d5a688" }, { "id": "fragment.observer", @@ -133,13 +133,13 @@ "id": "producer.observer_routes", "path": "solstone/apps/observer/routes.py", "role": "producer", - "sha256": "129ffa85173470af419c27553f974bdf52ce26b32f57876f5cc90bc866889539" + "sha256": "b741543fe2c776a3b074c489af6f1e1490b27e937badeb60c7c125503f2e50b7" }, { "id": "producer.observer_utils", "path": "solstone/apps/observer/utils.py", "role": "producer", - "sha256": "9dff210886069f02c5ddf5e4a33832e58af108e90272af353f98d8fcdd7a58bc" + "sha256": "06f908e181709542dfd461cd89f66f0aad222c98e1164bef0dbcfa64a4e0776b" }, { "id": "producer.protocol", diff --git a/solstone/apps/network/contract.py b/solstone/apps/network/contract.py index 1f04f437b..f069a39a8 100644 --- a/solstone/apps/network/contract.py +++ b/solstone/apps/network/contract.py @@ -40,6 +40,19 @@ _LOCAL_ENDPOINT_SCHEMA = { }, } +_REVOKED_OBSERVER_SCHEMA = { + "type": "array", + "items": { + "type": "object", + "additionalProperties": False, + "properties": { + "name": {"type": "string"}, + "prefix": {"type": "string"}, + }, + "required": ["name", "prefix"], + }, +} + OPERATIONS: list[OperationSpec] = [ OperationSpec( operation_id="link.pairStart", @@ -54,8 +67,13 @@ OPERATIONS: list[OperationSpec] = [ fields=( FieldSpec("device_label", "string"), FieldSpec("role", "string"), + FieldSpec("same_machine", "boolean"), ), - example={"device_label": "Jer iPhone", "role": "phone"}, + example={ + "device_label": "Jer iPhone", + "role": "phone", + "same_machine": False, + }, ), responses=( ResponseSpec( @@ -83,8 +101,8 @@ OPERATIONS: list[OperationSpec] = [ ), _json_error( 403, - ("pl_revoked",), - "Access gate rejected a revoked paired-link identity.", + ("local_request_only", "pl_revoked"), + "Access gate rejected the pair-start request.", ), _json_error( 503, @@ -307,9 +325,22 @@ OPERATIONS: list[OperationSpec] = [ responses=( ResponseSpec( status=200, - description="The revoked fingerprint.", - named_fields=(FieldSpec("unpaired", "string", required=True),), - example={"unpaired": "sha256:abc123"}, + description="The revoked fingerprint and any observer records revoked with it.", + named_fields=( + FieldSpec("unpaired", "string", required=True), + FieldSpec( + "revoked_observers", + "array", + required=True, + raw_schema=_REVOKED_OBSERVER_SCHEMA, + ), + ), + example={ + "unpaired": "sha256:abc123", + "revoked_observers": [ + {"name": "phone-a", "prefix": "phone-a-"}, + ], + }, ), _json_error( 400, @@ -326,6 +357,11 @@ OPERATIONS: list[OperationSpec] = [ ("paired_device_not_found",), "No paired device matched the request.", ), + _json_error( + 500, + ("internal_error",), + "Observer revoke cascade failed after the device was unpaired.", + ), ), ), OperationSpec( diff --git a/solstone/convey/contract/observer_bundle.py b/solstone/convey/contract/observer_bundle.py index 9345b4256..f1114c452 100644 --- a/solstone/convey/contract/observer_bundle.py +++ b/solstone/convey/contract/observer_bundle.py @@ -20,7 +20,7 @@ from solstone.convey.contract.assemble import CALLOSUM_REGISTRY, build_document from solstone.observe import protocol INITIAL_BUNDLE_SEMVER = "1.0.0" -BUNDLE_SEMVER = "5.0.5" +BUNDLE_SEMVER = "5.0.6" GENERATOR_IDENTITY = "solstone.convey.contract.observer_bundle.v1" BUNDLE_SCHEMA_IDENTITY = "solstone.observer-client-contract-bundle.schema.v1" SCHEMA_DIALECT_URI = "https://json-schema.org/draft/2020-12/schema"