{"id":31265804,"url":"https://github.com/open-policy-agent/opa-csharp","last_synced_at":"2025-10-11T10:26:09.769Z","repository":{"id":226287903,"uuid":"768260346","full_name":"open-policy-agent/opa-csharp","owner":"open-policy-agent","description":"A driver to connect via C# to Open Policy Agent (OPA) deployments","archived":false,"fork":false,"pushed_at":"2025-10-05T01:11:10.000Z","size":521,"stargazers_count":6,"open_issues_count":1,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-10-06T21:58:52.222Z","etag":null,"topics":["opa","open-policy-agent","sdk-csharp","sdk-dotnet","sdk-net"],"latest_commit_sha":null,"homepage":"https://open-policy-agent.github.io/opa-csharp/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/open-policy-agent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-03-06T18:58:52.000Z","updated_at":"2025-10-05T01:11:13.000Z","dependencies_parsed_at":"2024-04-02T17:45:02.086Z","dependency_job_id":"878f197f-199c-4172-9efb-da56dbea577c","html_url":"https://github.com/open-policy-agent/opa-csharp","commit_stats":null,"previous_names":["styrainc/opa-csharp","styraoss/opa-csharp","open-policy-agent/opa-csharp"],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/open-policy-agent/opa-csharp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-policy-agent%2Fopa-csharp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-policy-agent%2Fopa-csharp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-policy-agent%2Fopa-csharp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-policy-agent%2Fopa-csharp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/open-policy-agent","download_url":"https://codeload.github.com/open-policy-agent/opa-csharp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-policy-agent%2Fopa-csharp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002542,"owners_count":26083400,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["opa","open-policy-agent","sdk-csharp","sdk-dotnet","sdk-net"],"created_at":"2025-09-23T15:01:35.025Z","updated_at":"2025-10-11T10:26:09.764Z","avatar_url":"https://github.com/open-policy-agent.png","language":"C#","funding_links":[],"categories":["Language and Platform Integrations"],"sub_categories":[".NET"],"readme":"# OPA C# SDK\n\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![NuGet Version](https://img.shields.io/nuget/v/OpenPolicyAgent.Opa?style=flat\u0026color=%2324b6e0)](https://www.nuget.org/packages/OpenPolicyAgent.Opa/)\n\n\u003e [!IMPORTANT]\n\u003e Reference documentation is available at \u003chttps://open-policy-agent.github.io/opa-csharp\u003e\n\nYou can use the OPA C# SDK to connect to [Open Policy Agent](https://www.openpolicyagent.org/) and [EOPA](https://github.com/open-policy-agent/eopa) deployments.\n\n## SDK Installation\n\n### Nuget\n\n```bash\ndotnet add package OpenPolicyAgent.Opa\n```\n\u003c!-- No SDK Installation [installation] --\u003e\n\n## SDK Example Usage (high-level)\n\nThe following examples assume an OPA server at `http://localhost:8181` equipped with the following Rego policy in `authz.rego`:\n\n```rego\npackage authz\nimport rego.v1\n\ndefault allow := false\nallow if input.subject == \"alice\"\n```\n\nand this `data.json`:\n\n```json\n{\n  \"roles\": {\n    \"admin\": [\"read\", \"write\"]\n  }\n}\n```\n\n### Simple Query\n\nFor a simple boolean response with input, use the SDK as follows:\n\n```csharp\nusing OpenPolicyAgent.Opa;\n\nstring opaUrl = \"http://localhost:8181\";\nOpaClient opa = new OpaClient(opaUrl);\n\nvar input = new Dictionary\u003cstring, object\u003e() {\n    {\"subject\", \"alice\"},\n    {\"action\", \"read\"},\n};\n\nbool allowed = false;\n\ntry\n{\n    allowed = await opa.Check(\"authz/allow\", input);\n}\ncatch (OpaException e)\n{\n    Console.WriteLine(\"exception while making request against OPA: \" + e);\n}\n\nConsole.WriteLine(\"allowed: \" + allowed);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eResult\u003c/summary\u003e\n\n```txt\nallowed: True\n```\n\n\u003c/details\u003e\n\n### Simple Query with Output\n\nThe `.Evaluate()` method can be used instead of `.Check()` for non-boolean output types:\n\n```csharp\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing OpenPolicyAgent.Opa;\n\nvar opaUrl = \"http://localhost:8181\";\nvar opa = new OpaClient(opaUrl);\n\nvar input = new Dictionary\u003cstring, string\u003e() {\n    {\"subject\", \"alice\"},\n    {\"action\", \"read\"},\n};\n\nvar result = new Dictionary\u003cstring, List\u003cstring\u003e\u003e();\n\ntry\n{\n    result = await opa.Evaluate\u003cDictionary\u003cstring, List\u003cstring\u003e\u003e\u003e(\"roles\", input);\n}\ncatch (OpaException e)\n{\n    Console.WriteLine(\"exception while making request against OPA: \" + e.Message);\n}\n\nConsole.WriteLine(\"content of data.roles:\");\nforeach (var pair in result)\n{\n    Console.Write(\"  {0} =\u003e [ \", pair.Key);\n    foreach (var item in pair.Value)\n    {\n        Console.Write(\"{0} \", item);\n    }\n    Console.WriteLine(\"]\");\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eResult\u003c/summary\u003e\n\n```txt\ncontent of data.roles:\n    admin =\u003e [ read write ]\n```\n\n\u003c/details\u003e\n\n### Default Rule\n\nFor evaluating the default rule (configured with your OPA service), use `EvaluateDefault`. `input` is optional, and left out in this example:\n\n```csharp\nusing OpenPolicyAgent.Opa;\n\nstring opaUrl = \"http://localhost:8181\";\nOpaClient opa = new OpaClient(opaUrl);\n\nbool allowed = false;\n\ntry {\n    allowed = await opa.EvaluateDefault\u003cbool();\n}\ncatch (OpaException e) {\n    Console.WriteLine(\"exception while making request against OPA: \" + e);\n}\n\nConsole.WriteLine(\"allowed: \" + allowed);\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eResult\u003c/summary\u003e\n\n```txt\nallowed: False\n```\n\n\u003c/details\u003e\n\n### Batched Queries\n\nEOPA supports executing many queries in a single request with the [Batch API][eopa-batch-api].\n\n   [eopa-batch-api]: https://github.com/open-policy-agent/eopa/blob/main/docs/eopa/reference/api-reference/batch-api.md\n\nThe OPA C# SDK has native support for EOPA's batch API, with a fallback behavior of sequentially executing single queries if the Batch API is unavailable (such as with open source Open Policy Agent).\n\n```csharp\nusing OpenPolicyAgent.Opa;\n\nstring opaUrl = \"http://localhost:8181\";\nOpaClient opa = new OpaClient(opaUrl);\n\nvar input = new Dictionary\u003cstring, Dictionary\u003cstring, object\u003e\u003e() {\n    { \"AAA\", new Dictionary\u003cstring, object\u003e() { { \"subject\", \"alice\" }, { \"action\", \"read\" } } },\n    { \"BBB\", new Dictionary\u003cstring, object\u003e() { { \"subject\", \"bob\" }, { \"action\", \"write\" } } },\n    { \"CCC\", new Dictionary\u003cstring, object\u003e() { { \"subject\", \"dave\" }, { \"action\", \"read\" } } },\n    { \"DDD\", new Dictionary\u003cstring, object\u003e() { { \"subject\", \"sybil\" }, { \"action\", \"write\" } } },\n};\n\nOpaBatchResults results = new OpaBatchResults();\nOpaBatchErrors errors = new OpaBatchErrors();\ntry\n{\n    (results, errors) = await opa.EvaluateBatch(\"authz/allow\", input);\n}\ncatch (OpaException e)\n{\n    Console.WriteLine(\"exception while making request against OPA: \" + e.Message);\n}\n\nConsole.WriteLine(\"Query results, by key:\");\nforeach (var pair in results)\n{\n    Console.WriteLine(\"  {0} =\u003e {1}\", pair.Key, pair.Value.Result.Boolean);\n}\n\nif (errors.Count \u003e 0)\n{\n    Console.WriteLine(\"Query errors, by key:\");\n    foreach (var pair in errors)\n    {\n        Console.WriteLine(\"  {0} =\u003e {1}\", pair.Key, pair.Value);\n    }\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eResult\u003c/summary\u003e\n\n```txt\nQuery results, by key:\n    AAA =\u003e True\n    BBB =\u003e False\n    CCC =\u003e False\n    DDD =\u003e False\n```\n\n\u003c/details\u003e\n\nSee the [API Documentation](https://open-policy-agent.github.io/opa-csharp/api/OpenPolicyAgent.Opa.OpenApi.Models.Components.Result.html) for reference on the properties and types available from a result.\n\n### Using Custom Classes for Input and Output\n\nUsing the OPA C# SDK, it can be more natural to use custom class types as inputs and outputs to a policy, rather than `System.Collections.Dictionary` (or `Collections.List`). Internally, the OPA C# SDK uses [`Newtonsoft.Json`](https://www.newtonsoft.com/json) to serialize and deserialize inputs and outputs JSON to the provided types.\n\nIn the example below, note:\n\n- Using an `enum` for an input field\n- Hiding the sensitive `UUID` with the `JsonIgnore` property\n- Deserializing the query response to a `bool`\n\n```csharp\nusing System;\nusing OpenPolicyAgent.Opa;\nusing Newtonsoft.Json;\nusing Newtonsoft.Json.Converters;\n\nnamespace Application\n{\n    class Program\n    {\n        public enum ActionType\n        {\n            invalid,\n            create,\n            read,\n            update,\n            delete\n        }\n\n        private class CustomRBACObject\n        {\n\n            [JsonProperty(\"user\")]\n            public string User = \"\";\n\n            [JsonProperty(\"action\")]\n            [JsonConverter(typeof(StringEnumConverter))]\n            public ActionType Action = ActionType.invalid;\n\n            [JsonIgnore]\n            public string UUID = System.Guid.NewGuid().ToString();\n\n            public CustomRBACObject() { }\n\n            public CustomRBACObject(string user, ActionType action)\n            {\n                User = user;\n                Action = action;\n            }\n        }\n\n        static async Task\u003cint\u003e Main(string[] args)\n        {\n            string opaUrl = \"http://localhost:8181\";\n            OpaClient opa = new OpaClient(opaUrl);\n\n            var input = new CustomRBACObject(\"bob\", ActionType.read);\n            Console.WriteLine(\"The JSON that OPA will receive: {{\\\"input\\\": {0}}}\", JsonConvert.SerializeObject(input));\n\n            bool allowed = false;\n            try\n            {\n                allowed = await opa.Evaluate\u003cbool\u003e(\"authz/allow\", input);\n            }\n            catch (OpaException e)\n            {\n                Console.WriteLine(\"exception while making request against OPA: \" + e.Message);\n            }\n\n            Console.WriteLine(\"allowed: \" + allowed);\n            return 0;\n        }\n    }\n}\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eResult\u003c/summary\u003e\n\n```txt\nThe JSON that OPA will receive: {\"input\": {\"user\":\"bob\",\"action\":\"read\"}}\nallowed: False\n```\n\n\u003c/details\u003e\n\n### Integrating logging with the OPA C# SDK\n\nThe OPA C# SDK uses opt-in, [compile-time source generated logging](https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator), which can be integrated as a part of the overall logs of a larger application.\n\nHere's a quick example:\n\n```csharp\nusing Microsoft.Extensions.Logging;\nusing OpenPolicyAgent.Opa;\n\ninternal class Program\n{\n    static async Task\u003cint\u003e Main(string[] args)\n    {\n        using ILoggerFactory factory = LoggerFactory.Create(builder =\u003e builder.AddConsole());\n        ILogger\u003cOpaClient\u003e logger = factory.CreateLogger\u003cOpaClient\u003e();\n\n        var opaURL = \"http://localhost:8181\";\n        OpaClient opa = new OpaClient(opaURL, logger);\n\n        logger.LogInformation(\"Initialized an OPA client for the OPA at: {Description}.\", opaURL);\n\n        var allow = await opa.Evaluate\u003cbool\u003e(\"this/rule/does/not/exist\", false);\n\n        return 0;\n    }\n}\n```\n\n\u003cdetails\u003e\n    \u003csummary\u003eResult\u003c/summary\u003e\n\n```log\ninfo: OpenPolicyAgent.Opa.OpaClient[0]\n      Initialized an OPA client for the OPA at: http://localhost:8181.\nwarn: OpenPolicyAgent.Opa.OpaClient[2066302899]\n      executing policy at 'this/rule/does/not/exist' succeeded, but OPA did not reply with a result\nUnhandled exception. OpaException: executing policy at 'this/rule/does/not/exist' succeeded, but OPA did not reply with a result\n    ...\n```\n\n\u003c/details\u003e\n\n\u003e [!NOTE]\n\u003e For low-level SDK usage, see the sections below.\n\n---\n\n# OPA OpenAPI SDK (low-level)\n\n\u003c!-- Start Summary [summary] --\u003e\n## Summary\n\nFor more information about the API: [EOPA documentation](https://github.com/open-policy-agent/eopa/docs)\n\u003c!-- End Summary [summary] --\u003e\n\n\u003c!-- Start Table of Contents [toc] --\u003e\n## Table of Contents\n\u003c!-- $toc-max-depth=2 --\u003e\n- [OPA C# SDK](#opa-c-sdk)\n  - [SDK Installation](#sdk-installation)\n  - [SDK Example Usage (high-level)](#sdk-example-usage-high-level)\n- [OPA OpenAPI SDK (low-level)](#opa-openapi-sdk-low-level)\n  - [SDK Example Usage](#sdk-example-usage)\n  - [Available Resources and Operations](#available-resources-and-operations)\n  - [Server Selection](#server-selection)\n  - [Error Handling](#error-handling)\n  - [Authentication](#authentication)\n  - [Community](#community)\n\n\u003c!-- End Table of Contents [toc] --\u003e\n\n\u003c!-- Start SDK Example Usage [usage] --\u003e\n## SDK Example Usage\n\n### Example 1\n\n```csharp\nusing OpenPolicyAgent.Opa.OpenApi;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Components;\n\nvar sdk = new OpaApiClient();\n\nvar res = await sdk.ExecuteDefaultPolicyWithInputAsync(\n    input: Input.CreateNumber(\n        4963.69D\n    ),\n    pretty: false,\n    acceptEncoding: GzipAcceptEncoding.Gzip\n);\n\n// handle response\n```\n\n### Example 2\n\n```csharp\nusing OpenPolicyAgent.Opa.OpenApi;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Requests;\n\nvar sdk = new OpaApiClient();\n\nExecutePolicyWithInputRequest req = new ExecutePolicyWithInputRequest() {\n    Path = \"app/rbac\",\n    RequestBody = new ExecutePolicyWithInputRequestBody() {\n        Input = Input.CreateBoolean(\n            false\n        ),\n    },\n};\n\nvar res = await sdk.ExecutePolicyWithInputAsync(req);\n\n// handle response\n```\n\n### Example 3\n\n```csharp\nusing OpenPolicyAgent.Opa.OpenApi;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Components;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Requests;\nusing System.Collections.Generic;\n\nvar sdk = new OpaApiClient();\n\nExecuteBatchPolicyWithInputRequest req = new ExecuteBatchPolicyWithInputRequest() {\n    Path = \"app/rbac\",\n    RequestBody = new ExecuteBatchPolicyWithInputRequestBody() {\n        Inputs = new Dictionary\u003cstring, Input\u003e() {\n            { \"key\", Input.CreateStr(\n                \"\u003cvalue\u003e\"\n            ) },\n        },\n    },\n};\n\nvar res = await sdk.ExecuteBatchPolicyWithInputAsync(req);\n\n// handle response\n```\n\u003c!-- End SDK Example Usage [usage] --\u003e\n\n\u003c!-- Start Available Resources and Operations [operations] --\u003e\n## Available Resources and Operations\n\n\u003cdetails open\u003e\n\u003csummary\u003eAvailable methods\u003c/summary\u003e\n\n### [OpaApiClient SDK](docs/sdks/opaapiclient/README.md)\n\n- [ExecuteDefaultPolicyWithInput](docs/sdks/opaapiclient/README.md#executedefaultpolicywithinput) - Execute the default decision  given an input\n- [ExecutePolicy](docs/sdks/opaapiclient/README.md#executepolicy) - Execute a policy\n- [ExecutePolicyWithInput](docs/sdks/opaapiclient/README.md#executepolicywithinput) - Execute a policy given an input\n- [ExecuteBatchPolicyWithInput](docs/sdks/opaapiclient/README.md#executebatchpolicywithinput) - Execute a policy given a batch of inputs\n- [CompileQueryWithPartialEvaluation](docs/sdks/opaapiclient/README.md#compilequerywithpartialevaluation) - Partially evaluate a query\n- [Health](docs/sdks/opaapiclient/README.md#health) - Verify the server is operational\n\n\u003c/details\u003e\n\u003c!-- End Available Resources and Operations [operations] --\u003e\n\n\u003c!-- Start Server Selection [server] --\u003e\n## Server Selection\n\n### Override Server URL Per-Client\n\nThe default server can be overridden globally by passing a URL to the `serverUrl: string` optional parameter when initializing the SDK client instance. For example:\n\n```csharp\nusing OpenPolicyAgent.Opa.OpenApi;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Components;\n\nvar sdk = new OpaApiClient(serverUrl: \"http://localhost:8181\");\n\nvar res = await sdk.ExecuteDefaultPolicyWithInputAsync(\n    input: Input.CreateNumber(\n        4963.69D\n    ),\n    pretty: false,\n    acceptEncoding: GzipAcceptEncoding.Gzip\n);\n\n// handle response\n```\n\u003c!-- End Server Selection [server] --\u003e\n\n\u003c!-- Start Error Handling [errors] --\u003e\n## Error Handling\n\nHandling errors in this SDK should largely match your expectations. All operations return a response object or throw an exception.\n\nBy default, an API error will raise a `OpenPolicyAgent.Opa.OpenApi.Models.Errors.SDKException` exception, which has the following properties:\n\n| Property      | Type                  | Description           |\n|---------------|-----------------------|-----------------------|\n| `Message`     | *string*              | The error message     |\n| `StatusCode`  | *int*                 | The HTTP status code  |\n| `RawResponse` | *HttpResponseMessage* | The raw HTTP response |\n| `Body`        | *string*              | The response content  |\n\nWhen custom error responses are specified for an operation, the SDK may also throw their associated exceptions. You can refer to respective *Errors* tables in SDK docs for more details on possible exception types for each operation. For example, the `ExecuteDefaultPolicyWithInputAsync` method throws the following exceptions:\n\n| Error Type                                   | Status Code | Content Type     |\n| -------------------------------------------- | ----------- | ---------------- |\n| OpenPolicyAgent.Opa.OpenApi.Models.Errors.ClientError  | 400, 404    | application/json |\n| OpenPolicyAgent.Opa.OpenApi.Models.Errors.ServerError  | 500         | application/json |\n| OpenPolicyAgent.Opa.OpenApi.Models.Errors.SDKException | 4XX, 5XX    | \\*/\\*            |\n\n### Example\n\n```csharp\nusing OpenPolicyAgent.Opa.OpenApi;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Components;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Errors;\n\nvar sdk = new OpaApiClient();\n\ntry\n{\n    var res = await sdk.ExecuteDefaultPolicyWithInputAsync(\n        input: Input.CreateNumber(\n            4963.69D\n        ),\n        pretty: false,\n        acceptEncoding: GzipAcceptEncoding.Gzip\n    );\n\n    // handle response\n}\ncatch (Exception ex)\n{\n    if (ex is ClientError)\n    {\n        // Handle exception data\n        throw;\n    }\n    else if (ex is Models.Errors.ServerError)\n    {\n        // Handle exception data\n        throw;\n    }\n    else if (ex is OpenPolicyAgent.Opa.OpenApi.Models.Errors.SDKException)\n    {\n        // Handle default exception\n        throw;\n    }\n}\n```\n\u003c!-- End Error Handling [errors] --\u003e\n\n\u003c!-- Start Authentication [security] --\u003e\n## Authentication\n\n### Per-Client Security Schemes\n\nThis SDK supports the following security scheme globally:\n\n| Name         | Type | Scheme      |\n| ------------ | ---- | ----------- |\n| `BearerAuth` | http | HTTP Bearer |\n\nTo authenticate with the API the `BearerAuth` parameter must be set when initializing the SDK client instance. For example:\n\n```csharp\nusing OpenPolicyAgent.Opa.OpenApi;\nusing OpenPolicyAgent.Opa.OpenApi.Models.Components;\n\nvar sdk = new OpaApiClient(bearerAuth: \"\u003cYOUR_BEARER_TOKEN_HERE\u003e\");\n\nvar res = await sdk.ExecuteDefaultPolicyWithInputAsync(\n    input: Input.CreateNumber(\n        4963.69D\n    ),\n    pretty: false,\n    acceptEncoding: GzipAcceptEncoding.Gzip\n);\n\n// handle response\n```\n\u003c!-- End Authentication [security] --\u003e\n\n\u003c!-- Placeholder for Future Speakeasy SDK Sections --\u003e\n\n## Community\n\nFor questions, discussions and announcements, please join\nthe OPA community on [Slack](https://slack.openpolicyagent.org/)!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-policy-agent%2Fopa-csharp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-policy-agent%2Fopa-csharp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-policy-agent%2Fopa-csharp/lists"}