diff --git a/cSpell.json b/cSpell.json index 17b4394825e6..6a73f41e5f50 100644 --- a/cSpell.json +++ b/cSpell.json @@ -1140,6 +1140,14 @@ "timerange" ] }, + { + "filename": "**/specification/healthdataaiservices/**/*.json", + "words": [ + "deidentification", + "deidentify", + "surrogation" + ] + }, { "filename": "**/specification/search/data-plane/Azure.Search/**/*.json", "words": [ diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/client.tsp b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/client.tsp new file mode 100644 index 000000000000..1ea6edc25d3a --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/client.tsp @@ -0,0 +1,13 @@ +/** + * PLACEHOLDER + * Add readme and sample + */ +import "./main.tsp"; +import "@azure-tools/typespec-client-generator-core"; + +using Azure.ClientGenerator.Core; + +// // This model is input only +// @@usage(HealthDataAIServices.Deidentification.DeidentifyOptions, Usage.input); +// // This models is input/output +// @@usage(HealthDataAIServices.Deidentification.DeidentifyJob, Usage.output); diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/CancelJob.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/CancelJob.json new file mode 100644 index 000000000000..a051052a05b1 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/CancelJob.json @@ -0,0 +1,40 @@ +{ + "title": "Cancel a De-Identify Job", + "operationId": "CancelJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "Canceled", + "createdAt": "2024-01-25T23:27:43.009Z", + "startedAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z", + "summary": { + "successful": 10, + "failed": 0, + "canceled": 2, + "total": 12, + "bytesProcessed": 4096 + } + } + } + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/CreateJob.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/CreateJob.json new file mode 100644 index 000000000000..3a15bd32b163 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/CreateJob.json @@ -0,0 +1,73 @@ +{ + "title": "Create a De-Identify Job", + "operationId": "CreateJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000", + "resource": { + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "NotStarted" + } + }, + "responses": { + "200": { + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "NotStarted", + "createdAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z" + } + }, + "201": { + "headers": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D" + }, + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "NotStarted", + "createdAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z" + } + } + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/Deidentify.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/Deidentify.json new file mode 100644 index 000000000000..b973893f09f0 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/Deidentify.json @@ -0,0 +1,34 @@ +{ + "title": "Realtime Synchronous Deidentification.", + "operationId": "Deidentify", + "parameters": { + "api-version": "2024-01-16-preview", + "body": { + "inputText": "Hello my name is John Smith.", + "operation": "Redact", + "dataType": "Plaintext", + "stringIndexType": "TextElement_v8", + "redactionFormat": "[{type}]" + } + }, + "responses": { + "200": { + "body": { + "outputText": "Hello my name is [name].", + "taggerResult": { + "entities": [ + { + "category": "Patient", + "offset": 17, + "length": 10, + "text": "John Smith", + "confidenceScore": 0.83 + } + ], + "stringIndexType": "TextElement_v8", + "etag": "0x000000000000000" + } + } + } + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/DeleteJob.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/DeleteJob.json new file mode 100644 index 000000000000..0f91d9fc3e6e --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/DeleteJob.json @@ -0,0 +1,12 @@ +{ + "title": "Delete a De-Identify Job", + "operationId": "DeleteJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "204": {} + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/GetJob.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/GetJob.json new file mode 100644 index 000000000000..47e9fc3a7ccc --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/GetJob.json @@ -0,0 +1,40 @@ +{ + "title": "Get a De-Identify Job", + "operationId": "GetJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "Succeeded", + "createdAt": "2024-01-25T23:27:43.009Z", + "startedAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z", + "summary": { + "successful": 10, + "failed": 0, + "canceled": 0, + "total": 10, + "bytesProcessed": 4096 + } + } + } + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/ListJobFiles.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/ListJobFiles.json new file mode 100644 index 000000000000..b3595c602077 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/ListJobFiles.json @@ -0,0 +1,38 @@ +{ + "title": "List processed files within a Job", + "operationId": "ListJobFiles", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "maxpagesize": 10, + "continuationToken": "K1JJRDpzOEtaQWZabUQrQUNBQUFBQUFBQUFBQT09I1JUOjEjVFJDOjEwI0ZQQzpBZ0VBQUFBTUFDUUFBQUFBQUE9PQ==", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "00000000-0000-0000-0000-000000000000", + "input": { + "path": "/documents/patient_doc_1", + "etag": "0x8DB638EEA0CC717" + }, + "output": { + "path": "_output/documents/patient_doc_1", + "etag": "0xAB298APO23099ZL" + }, + "status": "Failed", + "error": { + "code": "FileNotFound", + "message": "File was moved after job started.", + "target": "SourceFile", + "details": [] + } + } + ], + "nextLink": "https://deidtest.api.deid.azure.com/jobs/00000000-0000-0000-0000-000000000000/files?top=10&skip=10&maxpagesize=10" + } + } + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/ListJobs.json b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/ListJobs.json new file mode 100644 index 000000000000..bcdad1d927da --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/examples/2024-01-16-preview/ListJobs.json @@ -0,0 +1,46 @@ +{ + "title": "List De-Identify Jobs", + "operationId": "ListJobs", + "parameters": { + "api-version": "2024-01-16-preview", + "maxpagesize": 10, + "continuationToken": "K1JJRDpzOEtaQWZabUQrQUNBQUFBQUFBQUFBQT09I1JUOjEjVFJDOjEwI0ZQQzpBZ0VBQUFBTUFDUUFBQUFBQUE9PQ==", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "Succeeded", + "createdAt": "2024-01-25T23:27:43.009Z", + "startedAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z", + "summary": { + "successful": 10, + "failed": 0, + "canceled": 0, + "total": 10, + "bytesProcessed": 4096 + } + } + ], + "nextLink": "https://deidtest.api.deid.azure.com/jobs?top=10&skip=10&maxpagesize=10" + } + } + } +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/main.tsp b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/main.tsp new file mode 100644 index 000000000000..846499477391 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/main.tsp @@ -0,0 +1,44 @@ +import "@typespec/rest"; +import "@typespec/versioning"; +import "@azure-tools/typespec-azure-core"; +import "./routes.tsp"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Azure.Core; +using Azure.Core.Traits; + +#suppress "@azure-tools/typespec-azure-core/casing-style" +@useAuth(AadToken) +@service({ + title: "HealthDataAIServices.Deidentification Service", +}) +@server( + "https://{endpoint}", + "Azure Health Deidentification Service", + { + @doc("Url of your Deid Service.") + endpoint: string, + } +) +@versioned(HealthDataAIServices.Deidentification.Versions) +namespace HealthDataAIServices.Deidentification; + +@doc("The Azure Active Directory OAuth2 Flow") +model AadToken + is OAuth2Auth<[ + { + type: OAuth2FlowType.authorizationCode; + authorizationUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"; + tokenUrl: "https://login.microsoftonline.com/common/oauth2/token"; + scopes: ["https://deid.azure.com/.default"]; + } + ]>; + +#suppress "@azure-tools/typespec-azure-core/documentation-required" +@doc("The HealthDataAIServices.Deidentification service versions.") +enum Versions { + @useDependency(Azure.Core.Versions.v1_0_Preview_2) + v2024_01_16_preview: "2024-01-16-preview", +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/models.tsp b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/models.tsp new file mode 100644 index 000000000000..dd746c8ba057 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/models.tsp @@ -0,0 +1,373 @@ +import "@typespec/http"; +import "@typespec/rest"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using Azure.Core; + +namespace HealthDataAIServices.Deidentification; + +@doc("A job containing a batch of documents to deidentify.") +@resource("jobs") +model DeidentificationJob { + @key + @doc("The name of a job.") + @visibility("read") + @maxLength(36) + @minLength(3) // Must be 3 to match regex + @pattern("^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$") + name: string; + + @doc("Storage location to perform the operation on.") + sourceLocation: SourceStorageLocation; + + @doc("Target location to store output of operation.") + targetLocation: TargetStorageLocation; + + @doc("Operation to perform on the input documents.") + operation: OperationType = OperationType.Surrogate; + + @doc("Data type of the input documents.") + dataType: DocumentDataType = DocumentDataType.Plaintext; + + @maxLength(16) + @minLength(1) + @doc("Format of the redacted output. Only valid when Operation is Redact.") + redactionFormat?: string; + + // Readonly Properties + + @doc("Current status of a job.") + @visibility("read") + @pollingOperationParameter + status: JobStatus; + + @doc("Error when job fails in it's entirety.") + @visibility("read") + error?: Azure.Core.Foundations.Error; + + @doc("Date and time when the job was created.") + @visibility("read") + createdAt: utcDateTime; + + @doc("Date and time when the job was started.") + @visibility("read") + startedAt?: utcDateTime; + + @doc(""" + Date and time when the job was completed. + + If the job is canceled, this is the time when the job was canceled. + + If the job failed, this is the time when the job failed. + """) + @visibility("read") + lastUpdatedAt?: utcDateTime; + + @doc("Summary of a job. Exists only when the job is completed.") + @visibility("read") + summary?: JobSummary; +} + +@doc("File report once job has completed.") +@resource("files") +@parentResource(DeidentificationJob) +model HealthFileDetails { + @key + @doc("Id of the file report.") + @visibility("read") + id: string; + + @doc("File Location for the input.") + input: FileLocation; + + @doc("File Location for the output.") + output?: FileLocation; + + @doc("Status of the file.") + status: Azure.Core.Foundations.OperationState; + + @doc("Error when file fails.") + error?: Azure.Core.Foundations.Error; +} + +@doc("Location of a file.") +model FileLocation { + @doc("Absolute path to the file in storage.") + @maxLength(1024) + path: string; + + ...EtagProperty; +} + +@doc("Summary metrics the documents pertaining to a job.") +model JobSummary { + @doc("Number of blobs that have completed.") + successful: int32; + + @doc("Number of blobs that have failed.") + failed: int32; + + @doc("Number of blobs that have been canceled.") + canceled: int32; + + @doc("Number of blobs total.") + total: int32; + + @doc("Number of bytes processed.") + bytesProcessed: int64; +} + +@doc("List of statuses a job can have.") +@lroStatus +union JobStatus { + // Cannot use Azure.Core.Foundations.OperationState. because it is not a union type. + + NotStarted: "NotStarted", + + Running: "Running", + + @lroSucceeded + Succeeded: "Succeeded", + + @lroFailed + @doc("Job has completed with at least 1 file failing.") + PartialFailed: "PartialFailed", + + @lroFailed + Failed: "Failed", + + @lroCanceled + Canceled: "Canceled", + + string, +} + +@doc("Storage location.") +model SourceStorageLocation { + @doc("URL to storage location. Must be a valid Azure Storage SAS URI.") + location: url; + + @doc("Prefix to filter blobs by.") + @minLength(1) + @maxLength(1024) + prefix: string; + + @doc("List of extensions to filter blobs by.") + @minItems(1) + extensions: Array = ["*"]; +} + +@doc("Storage location.") +model TargetStorageLocation { + @doc("URL to storage location. Must be a valid Azure Storage SAS URI.") + @secret + location: url; + + @doc("Prefix to filter blobs by.") + @minLength(1) + @maxLength(1024) + prefix: string; +} + +@doc("Enum of supported Data Types.") +union DocumentDataType { + @doc("Plain text data type.") + Plaintext: "Plaintext", + + string, +} + +@doc("Enum of supported Operation Types.") +union OperationType { + @doc("Redact Operation will remove all entities of PHI and replace them with a placeholder value.") + Redact: "Redact", + + @doc("Surrogation Operation will replace all entities of PHI with a surrogate value.") + Surrogate: "Surrogate", + + @doc("Tag Operation will detect all entities of PHI, their type, and return their locations in the document.") + Tag: "Tag", + + string, +} + +// Source: Text Analytics +@doc("List of supported index encodings.") +union StringIndexType { + @doc("Iterates over graphemes as defined by the Unicode 8.0.0 standard.") + TextElement_v8: "TextElement_v8", + + @doc("Iterates over Unicode Code Points, the default scheme for Python 3.") + UnicodeCodePoint: "UnicodeCodePoint", + + @doc("Iterates over UTF-16 Code Units, the default scheme for JavaScript, Java, and .NET.") + Utf16CodeUnit: "Utf16CodeUnit", + + string, +} + +@doc("Request for synchronous De-Identify operation.") +model DeidentificationContent { + @doc("Input text to deidentify.") + @maxLength(100000) // 100KB + inputText: string; + + @doc("Operation to perform on the input.") + operation: OperationType = OperationType.Surrogate; + + @doc("Data type of the input.") + dataType: DocumentDataType = DocumentDataType.Plaintext; + + // This must be set as optional so it isn't included in sdk constructors. + // SDKs then overwrite it as internal with appropriate default value for that SDK. + @doc("Requested Encoding of the tag response indices.") + stringIndexType?: StringIndexType; + + @maxLength(16) + @doc("Format of the redacted output. Only valid when OperationType is Redact.") + redactionFormat?: string; +} + +@doc("Response for synchronous De-Identify operation.") +model DeidentificationResult { + @doc("Output text after de-identifying. Not available for Tag Operation.") + outputText?: string; + + @doc("Result of the tag operation. Only available for Tag Operation.") + taggerResult?: PhiTaggerResult; +} + +@doc("Result of the tag operation.") +model PhiTaggerResult { + @doc("List of entities detected in the input.") + entities: Array; + + @doc("Requested Encoding of the tag response indices.") + stringIndexType: StringIndexType = StringIndexType.TextElement_v8; + + @doc("Path to the file in the storage container.") + @maxLength(1024) // Max length for Blob Name + path?: string; + + ...EtagProperty; +} + +@doc("List of PHI Entities.") +union PhiCategory { + @doc("Unknown PHI Type.") + Unknown: "Unknown", + + @doc("Account Number.") + Account: "Account", + + @doc("Age.") + Age: "Age", + + @doc("Biological Identifier, such as a fingerprint or retinal scan") + BioID: "BioID", + + @doc("City.") + City: "City", + + @doc("Country or Region.") + CountryOrRegion: "CountryOrRegion", + + @doc("Date.") + Date: "Date", + + @doc("Device ID or serial numbers.") + Device: "Device", + + @doc("Doctor's Name.") + Doctor: "Doctor", + + @doc("Email Addresses.") + Email: "Email", + + @doc("Fax Number.") + Fax: "Fax", + + @doc("Health Plan ID Numbers.") + HealthPlan: "HealthPlan", + + @doc("Hospital Name.") + Hospital: "Hospital", + + @doc("Id Numbers. Such as a passport number.") + IDNum: "IDNum", + + @doc("IP Address.") + IPAddress: "IPAddress", + + @doc("License. Such as a driver's license or medical license") + License: "License", + + @doc("Location Other. Such as Golden Gate Park.") + LocationOther: "LocationOther", + + @doc("Medical Record Number.") + MedicalRecord: "MedicalRecord", + + @doc("Organization. Such as a company name") + Organization: "Organization", + + @doc("Patient Name.") + Patient: "Patient", + + @doc("Phone Number.") + Phone: "Phone", + + @doc("Profession.") + Profession: "Profession", + + @doc("Social Security Numbers in the US.") + SocialSecurity: "SocialSecurity", + + @doc("State") + State: "State", + + @doc("Street.") + Street: "Street", + + @doc("Web URL.") + Url: "Url", + + @doc("Usernames, such as a social media handle") + Username: "Username", + + @doc("Vehicle IDs, such as license plates or VIN numbers") + Vehicle: "Vehicle", + + @doc("Zip Code.") + Zip: "Zip", + + string, +} + +@doc("Phi Entity tag in the input.") +model PhiEntity { + @doc("Phi Category of the entity.") + category: PhiCategory; + + @doc("Starting index of the location from within the input text.") + offset: int32; + + @doc("Length of the input text.") + length: int32; + + @doc("Text of the entity.") + text?: string; + + @doc("Confidence score of the text/type pairing.") + confidenceScore?: float64; +} + +@doc("Query parameters for listing jobs.") +model PaginationByTokenQueryParameters { + ...MaxPageSizeQueryParameter; + + @query + @doc("Token to continue a previous query.") + continuationToken?: string; +} diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/routes.tsp b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/routes.tsp new file mode 100644 index 000000000000..534892ff7126 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/routes.tsp @@ -0,0 +1,74 @@ +import "@azure-tools/typespec-azure-core"; +import "@typespec/http"; +import "@typespec/rest"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using TypeSpec.Versioning; +using Azure.Core; +using Azure.Core.Traits; + +namespace HealthDataAIServices.Deidentification; + +alias ServiceTraits = NoRepeatableRequests & + NoConditionalRequests & + SupportsClientRequestId; + +alias DeidentifyOperations = ResourceOperations< + ServiceTraits, + Azure.Core.Foundations.ErrorResponse +>; + +// Text-Deidentification Operations + +@summary("Create a De-Identify Job") +@pollingOperation(getJob) +op createJob is DeidentifyOperations.LongRunningResourceCreateOrReplace; + +@summary("Get a De-Identify Job") +op getJob is DeidentifyOperations.ResourceRead; + +@summary("List De-Identify Jobs") +op listJobs is DeidentifyOperations.ResourceList< + DeidentificationJob, + ListQueryParametersTrait +>; + +@summary("List processed files within a Job") +op listJobFiles is DeidentifyOperations.ResourceList< + HealthFileDetails, + ListQueryParametersTrait +>; + +#suppress "@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops" "" +@summary("Cancel a De-Identify Job") +@doc(""" + Cancels a job that is in progress. + + The job will be marked as canceled and the service will stop processing the job. The service will not delete any files that have already been processed. + + If the job is already complete, this will have no effect. + """) +@action("cancel") +op cancelJob is DeidentifyOperations.ResourceAction< + DeidentificationJob, + {}, + DeidentificationJob +>; + +@summary("Delete a De-Identify Job") +@doc("Removes the record of the job from the service. Does not delete any files.") +op deleteJob is DeidentifyOperations.ResourceDelete; + +@summary("Realtime Synchronous Deidentification.") +@route("/deid") +@post +op deidentify is Azure.Core.RpcOperation< + { + @doc("The request body for realtime deidentification.") + @body + body: DeidentificationContent; + }, + DeidentificationResult +>; diff --git a/specification/healthdataaiservices/HealthDataAIServices.Deidentification/tspconfig.yaml b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/tspconfig.yaml new file mode 100644 index 000000000000..71cdb90bd200 --- /dev/null +++ b/specification/healthdataaiservices/HealthDataAIServices.Deidentification/tspconfig.yaml @@ -0,0 +1,42 @@ +parameters: + "service-dir": + default: "sdk/healthdataaiservices" + "dependencies": + "additionalDirectories": [] + default: "" +emit: + - "@azure-tools/typespec-autorest" +options: + "@azure-tools/typespec-autorest": + azure-resource-provider-folder: "data-plane" + emitter-output-dir: "{project-root}/.." + examples-directory: "{project-root}/examples/" + output-file: "{project-root}/../data-plane/{service-name}/{version-status}/{version}/{service-name}.json" + omit-unreachable-types: true + "@azure-tools/typespec-python": + package-dir: "azure-health-deidentification" + package-name: "{package-dir}" + package-mode: dataplane + flavor: azure + "@azure-tools/typespec-csharp": + package-dir: "Azure.Health.Deidentification" + namespace: "{package-dir}" + clear-output-folder: true + model-namespace: false + flavor: azure + "@azure-tools/typespec-ts": + package-dir: "azure-health-deidentification" + generateMetadata: true + generateTest: true + packageDetails: + name: "@azure-rest/health-deidentification" + description: "Health Deidentification Service" + flavor: azure + "@azure-tools/typespec-java": + package-dir: "azure-health-deidentification" + namespace: "com.azure.health.deidentification" + customization-class: customization/src/main/java/HealthDeidentificationSdkCustomization.java + flavor: azure +linter: + extends: + - "@azure-tools/typespec-azure-core/all" diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/HealthDataAIServices.Deidentification.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/HealthDataAIServices.Deidentification.json new file mode 100644 index 000000000000..4596bc80d8a7 --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/HealthDataAIServices.Deidentification.json @@ -0,0 +1,1376 @@ +{ + "swagger": "2.0", + "info": { + "title": "HealthDataAIServices.Deidentification Service", + "version": "2024-01-16-preview", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "x-ms-parameterized-host": { + "hostTemplate": "https://{endpoint}", + "useSchemePrefix": false, + "parameters": [ + { + "name": "endpoint", + "in": "path", + "description": "Url of your Deid Service.", + "required": true, + "type": "string" + } + ] + }, + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "AadToken": [ + "https://deid.azure.com/.default" + ] + } + ], + "securityDefinitions": { + "AadToken": { + "type": "oauth2", + "description": "The Azure Active Directory OAuth2 Flow", + "flow": "accessCode", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", + "scopes": { + "https://deid.azure.com/.default": "" + }, + "tokenUrl": "https://login.microsoftonline.com/common/oauth2/token" + } + }, + "tags": [], + "paths": { + "/deid": { + "post": { + "operationId": "Deidentify", + "summary": "Realtime Synchronous Deidentification.", + "description": "A remote procedure call (RPC) operation.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "body", + "in": "body", + "description": "The request body for realtime deidentification.", + "required": true, + "schema": { + "$ref": "#/definitions/DeidentificationContent" + } + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/DeidentificationResult" + } + }, + "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": { + "Realtime Synchronous Deidentification.": { + "$ref": "./examples/Deidentify.json" + } + } + } + }, + "/jobs": { + "get": { + "operationId": "ListJobs", + "summary": "List De-Identify Jobs", + "description": "Resource list operation template.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "$ref": "#/parameters/Azure.Core.MaxPageSizeQueryParameter" + }, + { + "$ref": "#/parameters/PaginationByTokenQueryParameters.continuationToken" + }, + { + "$ref": "#/parameters/Azure.Core.ClientRequestIdHeader" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/PagedDeidentificationJob" + }, + "headers": { + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "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": { + "List De-Identify Jobs": { + "$ref": "./examples/ListJobs.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/jobs/{name}": { + "get": { + "operationId": "GetJob", + "summary": "Get a De-Identify Job", + "description": "Resource read operation template.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "name", + "in": "path", + "description": "The name of a job.", + "required": true, + "type": "string", + "minLength": 3, + "maxLength": 36, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$" + }, + { + "$ref": "#/parameters/Azure.Core.ClientRequestIdHeader" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/DeidentificationJob" + }, + "headers": { + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "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": { + "Get a De-Identify Job": { + "$ref": "./examples/GetJob.json" + } + } + }, + "put": { + "operationId": "CreateJob", + "summary": "Create a De-Identify Job", + "description": "Long-running resource create or replace operation template.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "name", + "in": "path", + "description": "The name of a job.", + "required": true, + "type": "string", + "minLength": 3, + "maxLength": 36, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$" + }, + { + "$ref": "#/parameters/Azure.Core.ClientRequestIdHeader" + }, + { + "name": "resource", + "in": "body", + "description": "The resource instance.", + "required": true, + "schema": { + "$ref": "#/definitions/DeidentificationJob" + } + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/DeidentificationJob" + }, + "headers": { + "Operation-Location": { + "type": "string", + "format": "uri", + "description": "The location for monitoring the operation state." + }, + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "201": { + "description": "The request has succeeded and a new resource has been created as a result.", + "schema": { + "$ref": "#/definitions/DeidentificationJob" + }, + "headers": { + "Operation-Location": { + "type": "string", + "format": "uri", + "description": "The location for monitoring the operation state." + }, + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "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": { + "Create a De-Identify Job": { + "$ref": "./examples/CreateJob.json" + } + }, + "x-ms-long-running-operation": true + }, + "delete": { + "operationId": "DeleteJob", + "summary": "Delete a De-Identify Job", + "description": "Removes the record of the job from the service. Does not delete any files.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "name", + "in": "path", + "description": "The name of a job.", + "required": true, + "type": "string", + "minLength": 3, + "maxLength": 36, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$" + }, + { + "$ref": "#/parameters/Azure.Core.ClientRequestIdHeader" + } + ], + "responses": { + "204": { + "description": "There is no content to send for this request, but the headers may be useful. ", + "headers": { + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "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": { + "Delete a De-Identify Job": { + "$ref": "./examples/DeleteJob.json" + } + } + } + }, + "/jobs/{name}:cancel": { + "post": { + "operationId": "CancelJob", + "summary": "Cancel a De-Identify Job", + "description": "Cancels a job that is in progress. \n\nThe job will be marked as canceled and the service will stop processing the job. The service will not delete any files that have already been processed.\n\nIf the job is already complete, this will have no effect. ", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "name", + "in": "path", + "description": "The name of a job.", + "required": true, + "type": "string", + "minLength": 3, + "maxLength": 36, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$" + }, + { + "$ref": "#/parameters/Azure.Core.ClientRequestIdHeader" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/DeidentificationJob" + }, + "headers": { + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "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": { + "Cancel a De-Identify Job": { + "$ref": "./examples/CancelJob.json" + } + } + } + }, + "/jobs/{name}/files": { + "get": { + "operationId": "ListJobFiles", + "summary": "List processed files within a Job", + "description": "Resource list operation template.", + "parameters": [ + { + "$ref": "#/parameters/Azure.Core.Foundations.ApiVersionParameter" + }, + { + "name": "name", + "in": "path", + "description": "The name of a job.", + "required": true, + "type": "string", + "minLength": 3, + "maxLength": 36, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$" + }, + { + "$ref": "#/parameters/Azure.Core.MaxPageSizeQueryParameter" + }, + { + "$ref": "#/parameters/PaginationByTokenQueryParameters.continuationToken" + }, + { + "$ref": "#/parameters/Azure.Core.ClientRequestIdHeader" + } + ], + "responses": { + "200": { + "description": "The request has succeeded.", + "schema": { + "$ref": "#/definitions/PagedHealthFileDetails" + }, + "headers": { + "x-ms-client-request-id": { + "type": "string", + "format": "uuid", + "description": "An opaque, globally-unique, client-generated string identifier for the request." + } + } + }, + "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": { + "List processed files within a Job": { + "$ref": "./examples/ListJobFiles.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "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." + } + } + }, + "Azure.Core.Foundations.OperationState": { + "type": "string", + "description": "Enum describing allowed operation states.", + "enum": [ + "NotStarted", + "Running", + "Succeeded", + "Failed", + "Canceled" + ], + "x-ms-enum": { + "name": "OperationState", + "modelAsString": true, + "values": [ + { + "name": "NotStarted", + "value": "NotStarted", + "description": "The operation has not started." + }, + { + "name": "Running", + "value": "Running", + "description": "The operation is in progress." + }, + { + "name": "Succeeded", + "value": "Succeeded", + "description": "The operation has completed successfully." + }, + { + "name": "Failed", + "value": "Failed", + "description": "The operation has failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "The operation has been canceled by the user." + } + ] + } + }, + "Azure.Core.eTag": { + "type": "string", + "description": "The ETag (or entity tag) HTTP response header is an identifier for a specific version of a resource.\nIt lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content was not changed.\n\nIt is a string of ASCII characters placed between double quotes, like \"675af34563dc-tr34\"." + }, + "DeidentificationContent": { + "type": "object", + "description": "Request for synchronous De-Identify operation.", + "properties": { + "inputText": { + "type": "string", + "description": "Input text to deidentify.", + "maxLength": 100000 + }, + "operation": { + "type": "string", + "description": "Operation to perform on the input.", + "default": "Surrogate", + "enum": [ + "Redact", + "Surrogate", + "Tag" + ], + "x-ms-enum": { + "name": "OperationType", + "modelAsString": true, + "values": [ + { + "name": "Redact", + "value": "Redact", + "description": "Redact Operation will remove all entities of PHI and replace them with a placeholder value." + }, + { + "name": "Surrogate", + "value": "Surrogate", + "description": "Surrogation Operation will replace all entities of PHI with a surrogate value." + }, + { + "name": "Tag", + "value": "Tag", + "description": "Tag Operation will detect all entities of PHI, their type, and return their locations in the document." + } + ] + } + }, + "dataType": { + "type": "string", + "description": "Data type of the input.", + "default": "Plaintext", + "enum": [ + "Plaintext" + ], + "x-ms-enum": { + "name": "DocumentDataType", + "modelAsString": true, + "values": [ + { + "name": "Plaintext", + "value": "Plaintext", + "description": "Plain text data type." + } + ] + } + }, + "stringIndexType": { + "$ref": "#/definitions/StringIndexType", + "description": "Requested Encoding of the tag response indices." + }, + "redactionFormat": { + "type": "string", + "description": "Format of the redacted output. Only valid when OperationType is Redact.", + "maxLength": 16 + } + }, + "required": [ + "inputText", + "operation", + "dataType" + ] + }, + "DeidentificationJob": { + "type": "object", + "description": "A job containing a batch of documents to deidentify.", + "properties": { + "name": { + "type": "string", + "description": "The name of a job.", + "minLength": 3, + "maxLength": 36, + "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]+[a-zA-Z0-9]$", + "readOnly": true + }, + "sourceLocation": { + "$ref": "#/definitions/SourceStorageLocation", + "description": "Storage location to perform the operation on." + }, + "targetLocation": { + "$ref": "#/definitions/TargetStorageLocation", + "description": "Target location to store output of operation." + }, + "operation": { + "type": "string", + "description": "Operation to perform on the input documents.", + "default": "Surrogate", + "enum": [ + "Redact", + "Surrogate", + "Tag" + ], + "x-ms-enum": { + "name": "OperationType", + "modelAsString": true, + "values": [ + { + "name": "Redact", + "value": "Redact", + "description": "Redact Operation will remove all entities of PHI and replace them with a placeholder value." + }, + { + "name": "Surrogate", + "value": "Surrogate", + "description": "Surrogation Operation will replace all entities of PHI with a surrogate value." + }, + { + "name": "Tag", + "value": "Tag", + "description": "Tag Operation will detect all entities of PHI, their type, and return their locations in the document." + } + ] + } + }, + "dataType": { + "type": "string", + "description": "Data type of the input documents.", + "default": "Plaintext", + "enum": [ + "Plaintext" + ], + "x-ms-enum": { + "name": "DocumentDataType", + "modelAsString": true, + "values": [ + { + "name": "Plaintext", + "value": "Plaintext", + "description": "Plain text data type." + } + ] + } + }, + "redactionFormat": { + "type": "string", + "description": "Format of the redacted output. Only valid when Operation is Redact.", + "minLength": 1, + "maxLength": 16 + }, + "status": { + "$ref": "#/definitions/JobStatus", + "description": "Current status of a job.", + "readOnly": true + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error when job fails in it's entirety.", + "readOnly": true + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Date and time when the job was created.", + "readOnly": true + }, + "startedAt": { + "type": "string", + "format": "date-time", + "description": "Date and time when the job was started.", + "readOnly": true + }, + "lastUpdatedAt": { + "type": "string", + "format": "date-time", + "description": "Date and time when the job was completed.\n\nIf the job is canceled, this is the time when the job was canceled.\n\nIf the job failed, this is the time when the job failed.", + "readOnly": true + }, + "summary": { + "$ref": "#/definitions/JobSummary", + "description": "Summary of a job. Exists only when the job is completed.", + "readOnly": true + } + }, + "required": [ + "name", + "sourceLocation", + "targetLocation", + "operation", + "dataType", + "status", + "createdAt" + ] + }, + "DeidentificationResult": { + "type": "object", + "description": "Response for synchronous De-Identify operation.", + "properties": { + "outputText": { + "type": "string", + "description": "Output text after de-identifying. Not available for Tag Operation." + }, + "taggerResult": { + "$ref": "#/definitions/PhiTaggerResult", + "description": "Result of the tag operation. Only available for Tag Operation." + } + } + }, + "FileLocation": { + "type": "object", + "description": "Location of a file.", + "properties": { + "path": { + "type": "string", + "description": "Absolute path to the file in storage.", + "maxLength": 1024 + }, + "etag": { + "$ref": "#/definitions/Azure.Core.eTag", + "description": "The entity tag for this resource.", + "readOnly": true + } + }, + "required": [ + "path", + "etag" + ] + }, + "HealthFileDetails": { + "type": "object", + "description": "File report once job has completed.", + "properties": { + "id": { + "type": "string", + "description": "Id of the file report.", + "readOnly": true + }, + "input": { + "$ref": "#/definitions/FileLocation", + "description": "File Location for the input." + }, + "output": { + "$ref": "#/definitions/FileLocation", + "description": "File Location for the output." + }, + "status": { + "$ref": "#/definitions/Azure.Core.Foundations.OperationState", + "description": "Status of the file." + }, + "error": { + "$ref": "#/definitions/Azure.Core.Foundations.Error", + "description": "Error when file fails." + } + }, + "required": [ + "id", + "input", + "status" + ] + }, + "JobStatus": { + "type": "string", + "description": "List of statuses a job can have.", + "enum": [ + "NotStarted", + "Running", + "Succeeded", + "PartialFailed", + "Failed", + "Canceled" + ], + "x-ms-enum": { + "name": "JobStatus", + "modelAsString": true, + "values": [ + { + "name": "NotStarted", + "value": "NotStarted" + }, + { + "name": "Running", + "value": "Running" + }, + { + "name": "Succeeded", + "value": "Succeeded" + }, + { + "name": "PartialFailed", + "value": "PartialFailed", + "description": "Job has completed with at least 1 file failing." + }, + { + "name": "Failed", + "value": "Failed" + }, + { + "name": "Canceled", + "value": "Canceled" + } + ] + } + }, + "JobSummary": { + "type": "object", + "description": "Summary metrics the documents pertaining to a job.", + "properties": { + "successful": { + "type": "integer", + "format": "int32", + "description": "Number of blobs that have completed." + }, + "failed": { + "type": "integer", + "format": "int32", + "description": "Number of blobs that have failed." + }, + "canceled": { + "type": "integer", + "format": "int32", + "description": "Number of blobs that have been canceled." + }, + "total": { + "type": "integer", + "format": "int32", + "description": "Number of blobs total." + }, + "bytesProcessed": { + "type": "integer", + "format": "int64", + "description": "Number of bytes processed." + } + }, + "required": [ + "successful", + "failed", + "canceled", + "total", + "bytesProcessed" + ] + }, + "PagedDeidentificationJob": { + "type": "object", + "description": "Paged collection of DeidentificationJob items", + "properties": { + "value": { + "type": "array", + "description": "The DeidentificationJob items on this page", + "items": { + "$ref": "#/definitions/DeidentificationJob" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "PagedHealthFileDetails": { + "type": "object", + "description": "Paged collection of HealthFileDetails items", + "properties": { + "value": { + "type": "array", + "description": "The HealthFileDetails items on this page", + "items": { + "$ref": "#/definitions/HealthFileDetails" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "PhiCategory": { + "type": "string", + "description": "List of PHI Entities.", + "enum": [ + "Unknown", + "Account", + "Age", + "BioID", + "City", + "CountryOrRegion", + "Date", + "Device", + "Doctor", + "Email", + "Fax", + "HealthPlan", + "Hospital", + "IDNum", + "IPAddress", + "License", + "LocationOther", + "MedicalRecord", + "Organization", + "Patient", + "Phone", + "Profession", + "SocialSecurity", + "State", + "Street", + "Url", + "Username", + "Vehicle", + "Zip" + ], + "x-ms-enum": { + "name": "PhiCategory", + "modelAsString": true, + "values": [ + { + "name": "Unknown", + "value": "Unknown", + "description": "Unknown PHI Type." + }, + { + "name": "Account", + "value": "Account", + "description": "Account Number." + }, + { + "name": "Age", + "value": "Age", + "description": "Age." + }, + { + "name": "BioID", + "value": "BioID", + "description": "Biological Identifier, such as a fingerprint or retinal scan" + }, + { + "name": "City", + "value": "City", + "description": "City." + }, + { + "name": "CountryOrRegion", + "value": "CountryOrRegion", + "description": "Country or Region." + }, + { + "name": "Date", + "value": "Date", + "description": "Date." + }, + { + "name": "Device", + "value": "Device", + "description": "Device ID or serial numbers." + }, + { + "name": "Doctor", + "value": "Doctor", + "description": "Doctor's Name." + }, + { + "name": "Email", + "value": "Email", + "description": "Email Addresses." + }, + { + "name": "Fax", + "value": "Fax", + "description": "Fax Number." + }, + { + "name": "HealthPlan", + "value": "HealthPlan", + "description": "Health Plan ID Numbers." + }, + { + "name": "Hospital", + "value": "Hospital", + "description": "Hospital Name." + }, + { + "name": "IDNum", + "value": "IDNum", + "description": "Id Numbers. Such as a passport number." + }, + { + "name": "IPAddress", + "value": "IPAddress", + "description": "IP Address." + }, + { + "name": "License", + "value": "License", + "description": "License. Such as a driver's license or medical license" + }, + { + "name": "LocationOther", + "value": "LocationOther", + "description": "Location Other. Such as Golden Gate Park." + }, + { + "name": "MedicalRecord", + "value": "MedicalRecord", + "description": "Medical Record Number." + }, + { + "name": "Organization", + "value": "Organization", + "description": "Organization. Such as a company name" + }, + { + "name": "Patient", + "value": "Patient", + "description": "Patient Name." + }, + { + "name": "Phone", + "value": "Phone", + "description": "Phone Number." + }, + { + "name": "Profession", + "value": "Profession", + "description": "Profession." + }, + { + "name": "SocialSecurity", + "value": "SocialSecurity", + "description": "Social Security Numbers in the US." + }, + { + "name": "State", + "value": "State", + "description": "State" + }, + { + "name": "Street", + "value": "Street", + "description": "Street." + }, + { + "name": "Url", + "value": "Url", + "description": "Web URL." + }, + { + "name": "Username", + "value": "Username", + "description": "Usernames, such as a social media handle" + }, + { + "name": "Vehicle", + "value": "Vehicle", + "description": "Vehicle IDs, such as license plates or VIN numbers" + }, + { + "name": "Zip", + "value": "Zip", + "description": "Zip Code." + } + ] + } + }, + "PhiEntity": { + "type": "object", + "description": "Phi Entity tag in the input.", + "properties": { + "category": { + "$ref": "#/definitions/PhiCategory", + "description": "Phi Category of the entity." + }, + "offset": { + "type": "integer", + "format": "int32", + "description": "Starting index of the location from within the input text." + }, + "length": { + "type": "integer", + "format": "int32", + "description": "Length of the input text." + }, + "text": { + "type": "string", + "description": "Text of the entity." + }, + "confidenceScore": { + "type": "number", + "format": "double", + "description": "Confidence score of the text/type pairing." + } + }, + "required": [ + "category", + "offset", + "length" + ] + }, + "PhiTaggerResult": { + "type": "object", + "description": "Result of the tag operation.", + "properties": { + "entities": { + "type": "array", + "description": "List of entities detected in the input.", + "items": { + "$ref": "#/definitions/PhiEntity" + }, + "x-ms-identifiers": [] + }, + "stringIndexType": { + "type": "string", + "description": "Requested Encoding of the tag response indices.", + "default": "TextElement_v8", + "enum": [ + "TextElement_v8", + "UnicodeCodePoint", + "Utf16CodeUnit" + ], + "x-ms-enum": { + "name": "StringIndexType", + "modelAsString": true, + "values": [ + { + "name": "TextElement_v8", + "value": "TextElement_v8", + "description": "Iterates over graphemes as defined by the Unicode 8.0.0 standard." + }, + { + "name": "UnicodeCodePoint", + "value": "UnicodeCodePoint", + "description": "Iterates over Unicode Code Points, the default scheme for Python 3." + }, + { + "name": "Utf16CodeUnit", + "value": "Utf16CodeUnit", + "description": "Iterates over UTF-16 Code Units, the default scheme for JavaScript, Java, and .NET." + } + ] + } + }, + "path": { + "type": "string", + "description": "Path to the file in the storage container.", + "maxLength": 1024 + }, + "etag": { + "$ref": "#/definitions/Azure.Core.eTag", + "description": "The entity tag for this resource.", + "readOnly": true + } + }, + "required": [ + "entities", + "stringIndexType", + "etag" + ] + }, + "SourceStorageLocation": { + "type": "object", + "description": "Storage location.", + "properties": { + "location": { + "type": "string", + "format": "uri", + "description": "URL to storage location. Must be a valid Azure Storage SAS URI." + }, + "prefix": { + "type": "string", + "description": "Prefix to filter blobs by.", + "minLength": 1, + "maxLength": 1024 + }, + "extensions": { + "type": "array", + "description": "List of extensions to filter blobs by.", + "default": [ + "*" + ], + "minItems": 1, + "items": { + "type": "string" + } + } + }, + "required": [ + "location", + "prefix", + "extensions" + ] + }, + "StringIndexType": { + "type": "string", + "description": "List of supported index encodings.", + "enum": [ + "TextElement_v8", + "UnicodeCodePoint", + "Utf16CodeUnit" + ], + "x-ms-enum": { + "name": "StringIndexType", + "modelAsString": true, + "values": [ + { + "name": "TextElement_v8", + "value": "TextElement_v8", + "description": "Iterates over graphemes as defined by the Unicode 8.0.0 standard." + }, + { + "name": "UnicodeCodePoint", + "value": "UnicodeCodePoint", + "description": "Iterates over Unicode Code Points, the default scheme for Python 3." + }, + { + "name": "Utf16CodeUnit", + "value": "Utf16CodeUnit", + "description": "Iterates over UTF-16 Code Units, the default scheme for JavaScript, Java, and .NET." + } + ] + } + }, + "TargetStorageLocation": { + "type": "object", + "description": "Storage location.", + "properties": { + "location": { + "type": "string", + "format": "password", + "description": "URL to storage location. Must be a valid Azure Storage SAS URI.", + "x-ms-secret": true + }, + "prefix": { + "type": "string", + "description": "Prefix to filter blobs by.", + "minLength": 1, + "maxLength": 1024 + } + }, + "required": [ + "location", + "prefix" + ] + } + }, + "parameters": { + "Azure.Core.ClientRequestIdHeader": { + "name": "x-ms-client-request-id", + "in": "header", + "description": "An opaque, globally-unique, client-generated string identifier for the request.", + "required": false, + "type": "string", + "format": "uuid", + "x-ms-parameter-location": "method", + "x-ms-client-name": "clientRequestId" + }, + "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" + }, + "Azure.Core.MaxPageSizeQueryParameter": { + "name": "maxpagesize", + "in": "query", + "description": "The maximum number of result items per page.", + "required": false, + "type": "integer", + "format": "int32", + "x-ms-parameter-location": "method" + }, + "PaginationByTokenQueryParameters.continuationToken": { + "name": "continuationToken", + "in": "query", + "description": "Token to continue a previous query.", + "required": false, + "type": "string", + "x-ms-parameter-location": "method" + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/CancelJob.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/CancelJob.json new file mode 100644 index 000000000000..a051052a05b1 --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/CancelJob.json @@ -0,0 +1,40 @@ +{ + "title": "Cancel a De-Identify Job", + "operationId": "CancelJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "Canceled", + "createdAt": "2024-01-25T23:27:43.009Z", + "startedAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z", + "summary": { + "successful": 10, + "failed": 0, + "canceled": 2, + "total": 12, + "bytesProcessed": 4096 + } + } + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/CreateJob.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/CreateJob.json new file mode 100644 index 000000000000..3a15bd32b163 --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/CreateJob.json @@ -0,0 +1,73 @@ +{ + "title": "Create a De-Identify Job", + "operationId": "CreateJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000", + "resource": { + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "NotStarted" + } + }, + "responses": { + "200": { + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "NotStarted", + "createdAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z" + } + }, + "201": { + "headers": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D" + }, + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "NotStarted", + "createdAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z" + } + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/Deidentify.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/Deidentify.json new file mode 100644 index 000000000000..b973893f09f0 --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/Deidentify.json @@ -0,0 +1,34 @@ +{ + "title": "Realtime Synchronous Deidentification.", + "operationId": "Deidentify", + "parameters": { + "api-version": "2024-01-16-preview", + "body": { + "inputText": "Hello my name is John Smith.", + "operation": "Redact", + "dataType": "Plaintext", + "stringIndexType": "TextElement_v8", + "redactionFormat": "[{type}]" + } + }, + "responses": { + "200": { + "body": { + "outputText": "Hello my name is [name].", + "taggerResult": { + "entities": [ + { + "category": "Patient", + "offset": 17, + "length": 10, + "text": "John Smith", + "confidenceScore": 0.83 + } + ], + "stringIndexType": "TextElement_v8", + "etag": "0x000000000000000" + } + } + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/DeleteJob.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/DeleteJob.json new file mode 100644 index 000000000000..0f91d9fc3e6e --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/DeleteJob.json @@ -0,0 +1,12 @@ +{ + "title": "Delete a De-Identify Job", + "operationId": "DeleteJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "204": {} + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/GetJob.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/GetJob.json new file mode 100644 index 000000000000..47e9fc3a7ccc --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/GetJob.json @@ -0,0 +1,40 @@ +{ + "title": "Get a De-Identify Job", + "operationId": "GetJob", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "Succeeded", + "createdAt": "2024-01-25T23:27:43.009Z", + "startedAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z", + "summary": { + "successful": 10, + "failed": 0, + "canceled": 0, + "total": 10, + "bytesProcessed": 4096 + } + } + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/ListJobFiles.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/ListJobFiles.json new file mode 100644 index 000000000000..b3595c602077 --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/ListJobFiles.json @@ -0,0 +1,38 @@ +{ + "title": "List processed files within a Job", + "operationId": "ListJobFiles", + "parameters": { + "api-version": "2024-01-16-preview", + "name": "documents_smith_1", + "maxpagesize": 10, + "continuationToken": "K1JJRDpzOEtaQWZabUQrQUNBQUFBQUFBQUFBQT09I1JUOjEjVFJDOjEwI0ZQQzpBZ0VBQUFBTUFDUUFBQUFBQUE9PQ==", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "00000000-0000-0000-0000-000000000000", + "input": { + "path": "/documents/patient_doc_1", + "etag": "0x8DB638EEA0CC717" + }, + "output": { + "path": "_output/documents/patient_doc_1", + "etag": "0xAB298APO23099ZL" + }, + "status": "Failed", + "error": { + "code": "FileNotFound", + "message": "File was moved after job started.", + "target": "SourceFile", + "details": [] + } + } + ], + "nextLink": "https://deidtest.api.deid.azure.com/jobs/00000000-0000-0000-0000-000000000000/files?top=10&skip=10&maxpagesize=10" + } + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/ListJobs.json b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/ListJobs.json new file mode 100644 index 000000000000..bcdad1d927da --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/preview/2024-01-16-preview/examples/ListJobs.json @@ -0,0 +1,46 @@ +{ + "title": "List De-Identify Jobs", + "operationId": "ListJobs", + "parameters": { + "api-version": "2024-01-16-preview", + "maxpagesize": 10, + "continuationToken": "K1JJRDpzOEtaQWZabUQrQUNBQUFBQUFBQUFBQT09I1JUOjEjVFJDOjEwI0ZQQzpBZ0VBQUFBTUFDUUFBQUFBQUE9PQ==", + "x-ms-client-request-id": "00000000-0000-0000-0000-000000000000" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "documents_smith_1", + "sourceLocation": { + "location": "https://blobtest.blob.core.windows.net/container?sp=r&st=2024-01-24T18:11:10Z&se=2024-01-25T02:11:10Z&spr=https&sv=2022-11-02&sr=c&sig=signature%3D", + "prefix": "/documents", + "extensions": [ + "*" + ] + }, + "targetLocation": { + "prefix": "/documents" + }, + "operation": "Redact", + "dataType": "Plaintext", + "redactionFormat": "[{type}]", + "status": "Succeeded", + "createdAt": "2024-01-25T23:27:43.009Z", + "startedAt": "2024-01-25T23:27:43.009Z", + "lastUpdatedAt": "2024-01-26T01:15:00.009Z", + "summary": { + "successful": 10, + "failed": 0, + "canceled": 0, + "total": 10, + "bytesProcessed": 4096 + } + } + ], + "nextLink": "https://deidtest.api.deid.azure.com/jobs?top=10&skip=10&maxpagesize=10" + } + } + } +} diff --git a/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/readme.md b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/readme.md new file mode 100644 index 000000000000..6adecdbfc540 --- /dev/null +++ b/specification/healthdataaiservices/data-plane/HealthDataAIServices.Deidentification/readme.md @@ -0,0 +1,78 @@ +# HealthDataAIServices.Deidentification + +> see https://aka.ms/autorest + +This is the AutoRest configuration file for HealthDataAIServices.Deidentification. + +## Getting Started + +To build the SDKs for My API, simply install AutoRest via `npm` (`npm install -g autorest`) and then run: + +> `autorest readme.md` + +To see additional help and options, run: + +> `autorest --help` + +For other options on installation see [Installing AutoRest](https://aka.ms/autorest/install) on the AutoRest github page. + +--- + +## Configuration + +### Basic Information + +These are the global settings for the HealthDataAIServices.Deidentification. + +```yaml +openapi-type: data-plane +tag: package-2024-01-16-preview +title: Health Deidentification Service +security: AADToken +security-scopes: + - "https://deid.azure.com/.default" +``` + +### Tag: package-2024-01-16-preview + +These settings apply only when `--tag=package-2024-01-16-preview` is specified on the command line. + +```yaml $(tag) == 'package-2024-01-16-preview' +input-file: + - preview/2024-01-16-preview/HealthDataAIServices.Deidentification.json +``` + +--- + +# Code Generation + +## Swagger to SDK + +This section describes what SDK should be generated by the automatic system. +This is not used by Autorest itself. + +```yaml $(swagger-to-sdk) +swagger-to-sdk: + - repo: azure-sdk-for-net-track2 + - repo: azure-sdk-for-python-track2 + - repo: azure-sdk-for-java + - repo: azure-sdk-for-js + - repo: azure-cli-extensions + - repo: azure-powershell +``` + +## Az + +See configuration in [readme.az.md](./readme.az.md) + +## Python + +See configuration in [readme.python.md](./readme.python.md) + +## TypeScript + +See configuration in [readme.typescript.md](./readme.typescript.md) + +## CSharp + +See configuration in [readme.csharp.md](./readme.csharp.md) \ No newline at end of file