chore(core): Test-Ready Service
Proposed Changes
- A "Test-Ready Service", which provides a pattern for integration testing. The idea here is to launch the platform server, along with some (arbitrary) service, which helps a developer to build unit and integration tests.
Checklist
- [ ] I have added or updated unit tests
- [ ] I have added or updated integration tests (if appropriate)
- [ ] I have added or updated documentation
Testing Instructions
- Follow all Quick Start steps in the main README
./.github/scripts/init-temp-keys.sh
docker-compose -f docker-compose.yaml up
cp opentdf-dev.yaml opentdf.yaml
go run ./service provision keycloak
- Exercise new tests, either using your IDE or a command-line (e.g.
go test -timeout 30s -run ^TestTRSIntegration$)- Note that this new test file will launch the platform server as a part of it's setup
Needs input 👈 Please provide your thoughts on this idea 📓
I think it'd be good to move all files (on the main branch) under examples/ to a new sub-directory examples/cli. Ideally, by organizing the file structure with trs and cli as siblings, it will highlight to a user of OpenTDF that these are distinct and separate concerns/examples.
Below is an example of the proposed file structure. If this is acceptable, I will git mv files in this Pull Request:
tree -L 2 examples/
examples/
├── cli
│ ├── cmd
│ ├── docs
│ ├── examples
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── README.md
└── trs
├── README.md
├── trs_test.go
└── trs.go
Benchmark results, click to expand
Benchmark Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 458.863281ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 367.852593ms |
| Throughput | 271.85 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 1m16.345822673s |
| Average Latency | 760.641423ms |
| Throughput | 65.49 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4947 |
| Failed Requests | 53 |
| Concurrent Requests | 50 |
| Total Time | 1m7.249212687s |
| Average Latency | 668.416963ms |
| Throughput | 73.56 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
53 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 448.43412ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 361.848478ms |
| Throughput | 276.36 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 1m16.199448008s |
| Average Latency | 760.157193ms |
| Throughput | 65.62 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4947 |
| Failed Requests | 53 |
| Concurrent Requests | 50 |
| Total Time | 1m7.130738373s |
| Average Latency | 667.303672ms |
| Throughput | 73.69 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
53 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 447.692533ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 374.914691ms |
| Throughput | 266.73 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 1m17.803821284s |
| Average Latency | 775.12415ms |
| Throughput | 64.26 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4942 |
| Failed Requests | 58 |
| Concurrent Requests | 50 |
| Total Time | 1m8.454421851s |
| Average Latency | 682.214431ms |
| Throughput | 72.19 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
58 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 475.62401ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 370.405422ms |
| Throughput | 269.97 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 1m23.069097104s |
| Average Latency | 827.416178ms |
| Throughput | 60.19 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4939 |
| Failed Requests | 61 |
| Concurrent Requests | 50 |
| Total Time | 1m14.17576188s |
| Average Latency | 740.103157ms |
| Throughput | 66.59 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
61 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 467.097191ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 365.003701ms |
| Throughput | 273.97 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 1m18.187641962s |
| Average Latency | 779.744465ms |
| Throughput | 63.95 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4937 |
| Failed Requests | 63 |
| Concurrent Requests | 50 |
| Total Time | 1m9.602809595s |
| Average Latency | 691.115731ms |
| Throughput | 70.93 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
63 occurrences |
Standard Benchmark Metrics Skipped or Failed
I was able to get all tests in this new service to pass using the following commands:
git clone [email protected]:opentdf/platform.git
cd platform
git checkout chore/add-trs
./.github/scripts/init-temp-keys.sh
docker-compose -f docker-compose.yaml up
# NEW TERMINAL TAB
cp opentdf-dev.yaml opentdf.yaml
go run ./service provision keycloak
cd examples/trs/
go test -timeout 30s -run ^TestTRSIntegration$
That said, I think we need a little more documentation on this service. What is the purpose? How should a developer use it?
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 418.191509ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 290.232196ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 351.278115ms |
| Throughput | 284.67 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 53.721441094s |
| Average Latency | 534.733184ms |
| Throughput | 93.07 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4972 |
| Failed Requests | 28 |
| Concurrent Requests | 50 |
| Total Time | 43.908124095s |
| Average Latency | 436.488511ms |
| Throughput | 113.24 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
28 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 459.500877ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 294.596996ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 347.107745ms |
| Throughput | 288.09 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 52.211099937s |
| Average Latency | 519.513786ms |
| Throughput | 95.77 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4941 |
| Failed Requests | 59 |
| Concurrent Requests | 50 |
| Total Time | 44.549648993s |
| Average Latency | 438.731125ms |
| Throughput | 110.91 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
59 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 444.769926ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 297.368601ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 346.626086ms |
| Throughput | 288.50 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 52.821606013s |
| Average Latency | 525.547212ms |
| Throughput | 94.66 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4948 |
| Failed Requests | 52 |
| Concurrent Requests | 50 |
| Total Time | 44.565182752s |
| Average Latency | 440.985456ms |
| Throughput | 111.03 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
52 occurrences |
Standard Benchmark Metrics Skipped or Failed
That said, I think we need a little more documentation on this service. What is the purpose? How should a developer use it?
@cakeholeDC I've expanded the README to give more insight about the purpose of this service. See: 9143114cc835c2c414f108f7c641c0e4d8a71d0a
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 465.767001ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 289.793752ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 348.739375ms |
| Throughput | 286.75 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 52.589328231s |
| Average Latency | 523.324445ms |
| Throughput | 95.08 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 4943 |
| Failed Requests | 57 |
| Concurrent Requests | 50 |
| Total Time | 43.273773359s |
| Average Latency | 428.419049ms |
| Throughput | 114.23 requests/second |
Error Summary:
| Error Message | Occurrences |
|---|---|
| ReadNanoTDF error: getNanoRewrapKey: rewrapError: internal: internal error rpc error: code = Internal desc = could not perform access |
57 occurrences |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 462.219626ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 297.112213ms |
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 344.56455ms |
| Throughput | 290.22 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.447767965s |
| Average Latency | 372.833521ms |
| Throughput | 133.52 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.229218036s |
| Average Latency | 260.999361ms |
| Throughput | 190.63 requests/second |
Standard Benchmark Metrics Skipped or Failed
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 439.583138ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 5000 |
| Denied Decision Requests | 0 |
| Total Time | 285.569898ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 350.685413ms |
| Throughput | 285.16 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.244027774s |
| Average Latency | 370.666898ms |
| Throughput | 134.25 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.227014449s |
| Average Latency | 261.541079ms |
| Throughput | 190.64 requests/second |
I've not seen much feedback on this PR, but I still think it is a useful example of a "Test-Ready Service", and just today was speaking with a teammate about some of the things that are included here (particularly the WithPublicRoutes, and other aspects of the server authz that can be configured).
I mistakenly ran go run ./service provision keycloak too quickly in testing after merging main into this branch locally...
User error, ignore this part 🤦
Everything worked as of commit 32b9ba8e68608196deffc226fc244421d984163b , but today when I merge main into this branch, you'll see that running (go run ./service provision keycloak) fails.
If you were to merge main into this branch (on your machine), and follow the Testing Instructions (see PR description), you'll get this error:
go run ./service provision keycloak
2025/07/10 11:45:34 ERROR error logging into keycloak error="could not get token: Post \"http://localhost:8888/auth/realms/master/protocol/openid-connect/token\": read tcp 127.0.0.1:61310->127.0.0.1:8888: read: connection reset by peer"
Error: could not get token: Post "http://localhost:8888/auth/realms/master/protocol/openid-connect/token": read tcp 127.0.0.1:61310->127.0.0.1:8888: read: connection reset by peer
Usage:
opentdf provision keycloak [flags]
Flags:
-e, --endpoint string Keycloak endpoint (default "http://localhost:8888/auth")
-f, --file string Keycloak config file (default "./service/cmd/keycloak_data.yaml")
-h, --help help for keycloak
-p, --password string Keycloak password (default "changeme")
-u, --username string Keycloak username (default "admin")
Global Flags:
--config-file string custom configuration file location
--config-key string the key is the name of the configuration file without the extension (default "opentdf")
2025/07/10 11:45:34 ERROR issue starting opentdf error="could not get token: Post \"http://localhost:8888/auth/realms/master/protocol/openid-connect/token\": read tcp 127.0.0.1:61310->127.0.0.1:8888: read: connection reset by peer"
exit status 1
After provisioning Keycloak, continue following the Testing Instructions.
There is an error:
go test -timeout 30s -run ^TestTRSIntegration$
2025/07/10 12:43:39 INFO trying to resolve absolute path path=/Users/b-long/.
2025/07/10 12:43:39 INFO adding path to search paths path=/Users/b-long
2025/07/10 12:43:39 INFO trying to resolve absolute path path=.
2025/07/10 12:43:39 INFO adding path to search paths path=/Users/b-long/Desktop/github/opentdf/platform.alternate
2025/07/10 12:43:39 INFO trying to resolve absolute path path=.
2025/07/10 12:43:39 INFO adding path to search paths path=/Users/b-long/Desktop/github/opentdf/platform.alternate
2025/07/10 12:43:39 INFO attempting to read in config file
time=2025-07-10T12:43:39.047-04:00 level=DEBUG msg="configuring otel tracer"
time=2025-07-10T12:43:39.047-04:00 level=INFO msg="tracing disabled."
time=2025-07-10T12:43:39.047-04:00 level=DEBUG msg="config loaded" config.dev_mode=false config.db.host=localhost config.db.port=5432 config.db.database=opentdf config.db.user=postgres config.db.password=[REDACTED] config.db.sslmode=prefer config.db.schema=opentdf config.db.connect_timeout_seconds=15 config.db.pool.max_connection_count=4 config.db.pool.min_connection_count=0 config.db.pool.max_connection_lifetime_seconds=3600 config.db.pool.max_connection_idle_seconds=1800 config.db.pool.health_check_period_seconds=60 config.db.runMigrations=true config.db.verifyConnection=true config.logger="{Level:debug Output:stdout Type:text}" config.mode=[all] config.sdk_config.core.endpoint="" config.sdk_config.core.plaintext=false config.sdk_config.core.insecure=false config.sdk_config.entityresolution.endpoint="" config.sdk_config.entityresolution.plaintext=false config.sdk_config.entityresolution.insecure=false config.sdk_config.client_id="" config.sdk_config.client_secret=[REDACTED] config.server.auth="{Enabled:true PublicRoutes:[] IPCReauthRoutes:[] AuthNConfig:{EnforceDPoP:false Issuer:http://localhost:8888/auth/realms/opentdf Audience:http://localhost:8080 Policy:{Builtin: UserNameClaim:preferred_username GroupsClaim:realm_access.roles RoleClaim:realm_access.roles RoleMap:map[] Csv: Extension:g, opentdf-admin, role:admin\ng, opentdf-standard, role:standard\n Model: Adapter:<nil>} CacheRefresh:15m DPoPSkew:1h0m0s TokenSkew:1m0s}}" config.server.grpc="{ReflectionEnabled:true MaxCallRecvMsgSizeBytes:4194304 MaxCallSendMsgSizeBytes:4194304}" config.server.tls="{Enabled:false Cert:./keys/platform.crt Key:./keys/platform-key.pem}" config.server.cors="{Enabled:true AllowedOrigins:[*] AllowedMethods:[GET POST PATCH PUT DELETE OPTIONS] AllowedHeaders:[ACCEPT Authorization Connect-Protocol-Version Content-Type X-CSRF-Token X-Request-ID] ExposedHeaders:[Link] AllowCredentials:true MaxAge:3600 Debug:false}" config.server.port=8080 config.server.host="" config.server.enablePprof=false config.server.cryptoProvider="{Type:standard StandardConfig:{Keys:[{Algorithm:rsa:2048 KID:r1 Private:kas-private.pem Certificate:kas-cert.pem Usage: Purpose:} {Algorithm:ec:secp256r1 KID:e1 Private:kas-ec-private.pem Certificate:kas-ec-cert.pem Usage: Purpose:}] RSAKeys:map[] ECKeys:map[]}}"
time=2025-07-10T12:43:39.047-04:00 level=INFO msg="creating cache manager"
time=2025-07-10T12:43:39.048-04:00 level=INFO msg="starting opentdf services"
time=2025-07-10T12:43:39.048-04:00 level=INFO msg="additional public routes added" routes=[/trs/**]
time=2025-07-10T12:43:39.048-04:00 level=DEBUG msg="initializing opentdf server"
time=2025-07-10T12:43:39.048-04:00 level=WARN msg="config Auth.EnforceDPoP is false. DPoP will not be enforced."
time=2025-07-10T12:43:39.048-04:00 level=DEBUG msg="discovering openid configuration" issuer=http://localhost:8888/auth/realms/opentdf
time=2025-07-10T12:43:39.608-04:00 level=INFO msg="initializing casbin enforcer"
time=2025-07-10T12:43:39.608-04:00 level=DEBUG msg="creating casbin enforcer" config="{PolicyConfig:{Builtin: UserNameClaim:preferred_username GroupsClaim:realm_access.roles RoleClaim:realm_access.roles RoleMap:map[] Csv:## Roles (prefixed with role:)\n# admin - admin\n# standard - standard\n# unknown - unknown role or no role\n\n## Resources\n# Resources beginning with / are HTTP routes. Generally, this does not matter, but when HTTP routes don't map well\n# with the protos this may become important.\n\n## Actions\n# read - read the resource\n# write - write to the resource\n# delete - delete the resource\n# unsafe - unsafe actions\n\n# Role: Admin\n## gRPC and HTTP routes\np,\trole:admin,\t\t*,\t\t\t\t\t*,\t\t\tallow\n\n## Role: Standard\n## gRPC routes\np,\trole:standard,\t\tpolicy.*,\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard,\t\tkasregistry.*,\t\t\t\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard, kas.AccessService/Rewrap, \t\t\t *,\t\t\tallow\np, role:standard, authorization.AuthorizationService/GetDecisions, read, allow\np, role:standard, authorization.AuthorizationService/GetDecisionsByToken, read, allow\np, role:standard, authorization.v2.AuthorizationService/GetDecision, read, allow\np, role:standard, authorization.v2.AuthorizationService/GetDecisionMultiResource, read, allow\np, role:standard, authorization.v2.AuthorizationService/GetDecisionBulk, read, allow\n\n## HTTP routes\np,\trole:standard,\t\t/attributes*,\t\t\t\t\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard,\t\t/namespaces*,\t\t\t\t\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard,\t\t/subject-mappings*,\t\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard,\t\t/resource-mappings*,\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard,\t\t/key-access-servers*,\t\t\t\t\t\t\t\t\t\tread,\t\t\tallow\np,\trole:standard,\t\t/kas/v2/rewrap,\t\t\t\t\t\t\t\t\t\t\t\t\twrite,\t\tallow\np, role:standard, /v1/authorization, write, allow\np, role:standard, /v1/token/authorization, write, allow\n\n# Public routes\n## gRPC routes\n## for ERS, right now we don't care about requester role, just that a valid jwt is provided when the OPA engine calls (enforced in the ERS itself, not casbin)\np,\trole:unknown, kas.AccessService/Rewrap, \t\t\t *,\t allow\n## HTTP routes\n## for ERS, right now we don't care about requester role, just that a valid jwt is provided when the OPA engine calls (enforced in the ERS itself, not casbin)\np,\trole:unknown,\t\t /kas/v2/rewrap,\t\t\t\t\t\t\t\t\t\t\t\t\t *,\t\tallow\ng, opentdf-admin, role:admin\ng, opentdf-standard, role:standard\n Extension:g, opentdf-admin, role:admin\ng, opentdf-standard, role:standard\n Model:[request_definition]\nr = sub,\tres,\tact\n\n[policy_definition]\np = sub,\tres,\tact,\teft\n\n[role_definition]\ng = _,\t_\n\n[policy_effect]\ne = some(where (p.eft == allow)) && !some(where (p.eft == deny))\n\n[matchers]\nm = g(r.sub,\tp.sub) && keyMatch(r.res,\tp.res) && keyMatch(r.act,\tp.act) Adapter:0x14000430920}}" isDefaultModel=true isBuiltinPolicy=true isPolicyExtended=true isDefaultAdapter=true
time=2025-07-10T12:43:39.805-04:00 level=DEBUG msg="authentication interceptor enabled"
time=2025-07-10T12:43:39.809-04:00 level=INFO msg="creating crypto provider" type=standard
time=2025-07-10T12:43:39.809-04:00 level=INFO msg="crypto cfg loading" id=r1 alg=rsa:2048
time=2025-07-10T12:43:39.810-04:00 level=INFO msg="crypto cfg loading" id=e1 alg=ec:secp256r1
time=2025-07-10T12:43:39.810-04:00 level=DEBUG msg="initializing service registry"
time=2025-07-10T12:43:39.810-04:00 level=DEBUG msg="registering essential services"
time=2025-07-10T12:43:39.810-04:00 level=INFO msg="registered service" namespace=health service=grpc.health.v1.Health
time=2025-07-10T12:43:39.810-04:00 level=DEBUG msg="registering services"
time=2025-07-10T12:43:39.810-04:00 level=INFO msg="registered service" namespace=authorization service=authorization.AuthorizationService
time=2025-07-10T12:43:39.810-04:00 level=INFO msg="registered service" namespace=authorization service=authorization.v2.AuthorizationService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=kas service=kas.AccessService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=wellknown service=wellknownconfiguration.WellKnownService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=entityresolution service=entityresolution.EntityResolutionService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=entityresolution service=entityresolution.v2.EntityResolutionService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.attributes.AttributesService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.namespaces.NamespaceService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.resourcemapping.ResourceMappingService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.subjectmapping.SubjectMappingService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.kasregistry.KeyAccessServerRegistryService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.unsafe.UnsafeService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.actions.ActionService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.registeredresources.RegisteredResourcesService
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=policy service=policy.keymanagement.KeyManagementService
time=2025-07-10T12:43:39.811-04:00 level=DEBUG msg="registering extra services"
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered service" namespace=trs service=trs
time=2025-07-10T12:43:39.811-04:00 level=INFO msg="registered the following core services" core_services="[policy authorization kas wellknown entityresolution]"
time=2025-07-10T12:43:39.885-04:00 level=INFO msg="starting services"
time=2025-07-10T12:43:39.885-04:00 level=DEBUG msg="creating database client" namespace=policy
time=2025-07-10T12:43:39.886-04:00 level=INFO msg="opening new database pool" schema=opentdf_policy
time=2025-07-10T12:43:40.146-04:00 level=DEBUG msg="successfully set database client search_path" schema=opentdf_policy
time=2025-07-10T12:43:40.151-04:00 level=INFO msg="running migration up" schema=opentdf_policy database=opentdf
time=2025-07-10T12:43:40.516-04:00 level=INFO msg="migration db info" current_version=0
time=2025-07-10T12:43:44.862-04:00 level=INFO msg="database notice" schema=opentdf_policy message="relation \"attribute_value_key_map\" does not exist, skipping"
signal: interrupt
FAIL github.com/opentdf/platform/examples/trs 6.646s
$ echo $?
1
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 168.393328ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 93.29339ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 339.129926ms |
| Throughput | 294.87 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 36.204357103s |
| Average Latency | 360.715018ms |
| Throughput | 138.10 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 25.577341816s |
| Average Latency | 255.068799ms |
| Throughput | 195.49 requests/second |
Test worked on my end using instructions in the description
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 176.978011ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 99.367412ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 361.119011ms |
| Throughput | 276.92 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.286150683s |
| Average Latency | 371.125018ms |
| Throughput | 134.10 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.142584783s |
| Average Latency | 260.479471ms |
| Throughput | 191.26 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 186.499006ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 96.587652ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 340.317939ms |
| Throughput | 293.84 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.108760878s |
| Average Latency | 369.029189ms |
| Throughput | 134.74 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 25.872793053s |
| Average Latency | 257.782707ms |
| Throughput | 193.25 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 182.138271ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 94.615718ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 364.267979ms |
| Throughput | 274.52 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 39.741887048s |
| Average Latency | 395.859704ms |
| Throughput | 125.81 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 27.338113608s |
| Average Latency | 272.37877ms |
| Throughput | 182.89 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 174.471604ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 97.627804ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 349.368113ms |
| Throughput | 286.23 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.847956s |
| Average Latency | 376.3479ms |
| Throughput | 132.11 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.441349332s |
| Average Latency | 263.46536ms |
| Throughput | 189.10 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 173.321432ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 100.013327ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 351.143188ms |
| Throughput | 284.78 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 38.099479446s |
| Average Latency | 378.028864ms |
| Throughput | 131.24 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.386117304s |
| Average Latency | 262.991087ms |
| Throughput | 189.49 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 170.391422ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 93.414758ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 347.11828ms |
| Throughput | 288.09 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 36.393877234s |
| Average Latency | 362.297539ms |
| Throughput | 137.39 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 25.396546005s |
| Average Latency | 252.954212ms |
| Throughput | 196.88 requests/second |
/gemini review
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 185.728173ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 100.532804ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 366.938693ms |
| Throughput | 272.53 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 39.101204318s |
| Average Latency | 388.678646ms |
| Throughput | 127.87 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 27.063957527s |
| Average Latency | 269.538327ms |
| Throughput | 184.75 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 172.691841ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 100.215642ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 348.373132ms |
| Throughput | 287.05 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.79035742s |
| Average Latency | 375.376027ms |
| Throughput | 132.31 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.300826137s |
| Average Latency | 262.159557ms |
| Throughput | 190.11 requests/second |
@b-long I haven't heard of the terminology "test-ready-service" is essentially an example how you could develop a PEP that utilizes the platform? (or that's how I read the code)
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 183.198303ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 95.299276ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 351.328221ms |
| Throughput | 284.63 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.195634191s |
| Average Latency | 370.442821ms |
| Throughput | 134.42 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 25.923020884s |
| Average Latency | 258.185596ms |
| Throughput | 192.88 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 152.990742ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 109.996035ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 351.806251ms |
| Throughput | 284.25 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 37.300362304s |
| Average Latency | 371.152201ms |
| Throughput | 134.05 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 26.002790179s |
| Average Latency | 259.102059ms |
| Throughput | 192.29 requests/second |
Benchmark results, click to expand
Benchmark authorization.GetDecisions Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 212.728849ms |
Benchmark authorization.v2.GetMultiResourceDecision Results:
| Metric | Value |
|---|---|
| Approved Decision Requests | 1000 |
| Denied Decision Requests | 0 |
| Total Time | 93.188052ms |
Standard Benchmark Metrics Skipped or Failed
Bulk Benchmark Results
| Metric | Value |
|---|---|
| Total Decrypts | 100 |
| Successful Decrypts | 100 |
| Failed Decrypts | 0 |
| Total Time | 340.953788ms |
| Throughput | 293.29 requests/second |
TDF3 Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 36.740847516s |
| Average Latency | 364.732473ms |
| Throughput | 136.09 requests/second |
NANOTDF Benchmark Results:
| Metric | Value |
|---|---|
| Total Requests | 5000 |
| Successful Requests | 5000 |
| Failed Requests | 0 |
| Concurrent Requests | 50 |
| Total Time | 25.70258936s |
| Average Latency | 256.076233ms |
| Throughput | 194.53 requests/second |
/gemini review