Skip to content

feat: Start ADR 0025 dynamic auth plugins implementation#911

Merged
gtema merged 1 commit into
mainfrom
claude/adr-0025-implementation-plan-adh5ii
Jul 3, 2026
Merged

feat: Start ADR 0025 dynamic auth plugins implementation#911
gtema merged 1 commit into
mainfrom
claude/adr-0025-implementation-plan-adh5ii

Conversation

@gtema

@gtema gtema commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Sequences the WASM plugin work into independently-mergeable phases
(runtime foundation, full_auth mode, mapping mode, route mode, admin
APIs), pinning implementation choices the ADR left open: a dedicated
dynamic-plugin-runtime crate, a Rust reference test plugin, and
mode-by-mode phasing with admin APIs deferred to the final phase.

Complete ADR 0025 Phase 0: reference plugin and resource-limit
enforcement

@gtema gtema force-pushed the claude/adr-0025-implementation-plan-adh5ii branch 2 times, most recently from 254f1f9 to e7b4939 Compare July 3, 2026 13:58
@gtema gtema changed the title docs: Add ADR 0025 dynamic auth plugins implementation plan feat: Start ADR 0025 dynamic auth plugins implementation Jul 3, 2026
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

🦢 Load Test Results

Goose Attack Report

Plan Overview

Action Started Stopped Elapsed Users
Increasing 26-07-03 18:12:48 26-07-03 18:13:04 00:00:16 0 → 30
Maintaining 26-07-03 18:13:04 26-07-03 18:13:34 00:00:30 30
Decreasing 26-07-03 18:13:34 26-07-03 18:13:34 00:00:00 0 ← 30

Request Metrics

Method Name # Requests # Fails Average (ms) Min (ms) Max (ms) RPS Failures/s
DELETE DELETE /v3/auth/tokens 478 0 113.96 24 154 15.93 0.00
DELETE DELETE /v3/projects/:id (teardown) 2 0 59.00 43 75 0.07 0.00
DELETE DELETE /v3/users/:id (teardown) 3 0 54.00 35 80 0.10 0.00
GET 4379 0 107.42 73 210 145.97 0.00
GET GET /v3/auth/tokens (validate new) 478 0 114.63 95 143 15.93 0.00
GET GET /v3/projects/:id 683 0 87.77 73 116 22.77 0.00
GET GET /v3/projects/:id (catalog) 676 0 88.13 76 114 22.53 0.00
GET GET /v3/users/:id 954 0 94.23 81 126 31.80 0.00
GET GET /v3/users/:id (catalog) 751 0 93.23 81 128 25.03 0.00
POST POST /v3/auth/tokens 475 0 86.32 76 119 15.83 0.00
Aggregated 8879 0 101.40 24 210 295.97 0.00

Response Time Metrics

Method Name 50%ile (ms) 60%ile (ms) 70%ile (ms) 80%ile (ms) 90%ile (ms) 95%ile (ms) 99%ile (ms) 100%ile (ms)
DELETE DELETE /v3/auth/tokens 110 120 120 120 120 120 130 150
DELETE DELETE /v3/projects/:id (teardown) 43 43 43 75 75 75 75 75
DELETE DELETE /v3/users/:id (teardown) 47 47 47 47 80 80 80 80
GET 99 100 110 110 160 170 180 210
GET GET /v3/auth/tokens (validate new) 110 120 120 120 120 130 140 140
GET GET /v3/projects/:id 87 88 90 92 95 98 110 116
GET GET /v3/projects/:id (catalog) 87 89 90 92 95 98 100 110
GET GET /v3/users/:id 94 95 96 98 100 100 110 126
GET GET /v3/users/:id (catalog) 93 94 95 97 99 100 110 128
POST POST /v3/auth/tokens 86 87 88 90 93 95 100 119
Aggregated 94 98 110 110 120 160 170 210

Status Code Metrics

Method Name Status Codes
DELETE DELETE /v3/auth/tokens 478 [204]
DELETE DELETE /v3/projects/:id (teardown) 2 [204]
DELETE DELETE /v3/users/:id (teardown) 3 [204]
GET 4,379 [200]
GET GET /v3/auth/tokens (validate new) 478 [200]
GET GET /v3/projects/:id 683 [200]
GET GET /v3/projects/:id (catalog) 676 [200]
GET GET /v3/users/:id 954 [200]
GET GET /v3/users/:id (catalog) 751 [200]
POST POST /v3/auth/tokens 475 [200]
Aggregated 483 [204], 8,396 [200]

Transaction Metrics

Transaction # Times Run # Fails Average (ms) Min (ms) Max (ms) RPS Failures/s
ReadHeavy
0.0 1 0 32.00 32 32 0.03 0.00
0.1 742 0 106.37 84 141 24.73 0.00
0.2 743 0 88.80 73 117 24.77 0.00
0.3 745 0 87.44 75 122 24.83 0.00
TokenLifecycle
1.0 0 0 0.00 0 0 0.00 0.00
1.1 478 0 316.08 205 356 15.93 0.00
ValidateToken
2.0 0 0 0.00 0 0 0.00 0.00
2.1 722 0 166.72 150 210 24.07 0.00
UserCRUD
3.0 0 0 0.00 0 0 0.00 0.00
3.1 0 0 0.00 0 0 0.00 0.00
3.2 954 0 94.29 81 126 31.80 0.00
3.3 3 0 54.00 35 80 0.10 0.00
ProjectCRUD
4.0 0 0 0.00 0 0 0.00 0.00
4.1 0 0 0.00 0 0 0.00 0.00
4.2 683 0 87.83 73 116 22.77 0.00
4.3 2 0 59.00 43 75 0.07 0.00
UserRead
5.0 0 0 0.00 0 0 0.00 0.00
5.1 750 0 106.57 94 137 25.00 0.00
5.2 751 0 93.27 81 128 25.03 0.00
ProjectRead
6.0 0 0 0.00 0 0 0.00 0.00
6.1 677 0 89.03 77 116 22.57 0.00
6.2 676 0 88.19 76 114 22.53 0.00
Aggregated 7927 0 113.58 32 356 264.23 0.00

Scenario Metrics

Transaction # Users # Times Run Average (ms) Min (ms) Max (ms) Scenarios/s Iterations
ReadHeavy 7 741 283.73 263 328 24.70 105.86
TokenLifecycle 5 473 316.69 297 356 15.77 94.60
ValidateToken 4 718 166.74 150 210 23.93 179.50
UserCRUD 3 951 94.31 81 126 31.70 317.00
ProjectCRUD 2 681 87.84 73 116 22.70 340.50
UserRead 5 749 200.42 182 237 24.97 149.80
ProjectRead 4 675 177.75 160 223 22.50 168.75
Aggregated 30 4988 180.30 73 356 166.27 1356.01

View full report

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

🐰 Bencher Report

Branchclaude/adr-0025-implementation-plan-adh5ii
Testbedubuntu-latest
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
nanoseconds (ns)
(Result Δ%)
Upper Boundary
nanoseconds (ns)
(Limit %)
Command_Serde/apply/remove📈 view plot
🚷 view threshold
132,410.00 ns
(-56.11%)Baseline: 301,687.91 ns
1,713,866.93 ns
(7.73%)
Command_Serde/apply/set📈 view plot
🚷 view threshold
143,340.00 ns
(-43.57%)Baseline: 254,012.20 ns
1,029,661.59 ns
(13.92%)
Command_Serde/pack/delete📈 view plot
🚷 view threshold
123.51 ns
(+1.61%)Baseline: 121.55 ns
146.29 ns
(84.43%)
Command_Serde/pack/delete_index📈 view plot
🚷 view threshold
113.04 ns
(+2.80%)Baseline: 109.96 ns
131.52 ns
(85.95%)
Command_Serde/pack/set📈 view plot
🚷 view threshold
200.87 ns
(+2.75%)Baseline: 195.50 ns
239.34 ns
(83.93%)
Command_Serde/pack/set_index📈 view plot
🚷 view threshold
112.26 ns
(+2.21%)Baseline: 109.84 ns
131.09 ns
(85.64%)
Command_Serde/unpack/delete📈 view plot
🚷 view threshold
193.04 ns
(+0.31%)Baseline: 192.44 ns
234.58 ns
(82.29%)
Command_Serde/unpack/delete_index📈 view plot
🚷 view threshold
160.23 ns
(+0.37%)Baseline: 159.65 ns
197.78 ns
(81.01%)
Command_Serde/unpack/set📈 view plot
🚷 view threshold
279.73 ns
(+4.49%)Baseline: 267.71 ns
333.04 ns
(83.99%)
Command_Serde/unpack/set_index📈 view plot
🚷 view threshold
156.97 ns
(-1.41%)Baseline: 159.21 ns
196.36 ns
(79.94%)
Payload_encryption/pack/remove_cmd📈 view plot
🚷 view threshold
133.80 ns
(+15.68%)Baseline: 115.67 ns
139.92 ns
(95.62%)
Payload_encryption/pack/set_cmd📈 view plot
🚷 view threshold
208.06 ns
(+2.57%)Baseline: 202.84 ns
267.56 ns
(77.76%)
Payload_encryption/unpack/remove_cmd📈 view plot
🚷 view threshold
211.19 ns
(+3.15%)Baseline: 204.75 ns
253.48 ns
(83.32%)
Payload_encryption/unpack/set_cmd📈 view plot
🚷 view threshold
296.02 ns
(+5.47%)Baseline: 280.67 ns
352.24 ns
(84.04%)
Raft_1Node_Latency/prefix/1node📈 view plot
🚷 view threshold
2,670,200.00 ns
(-1.85%)Baseline: 2,720,507.66 ns
6,216,923.89 ns
(42.95%)
Raft_1Node_Latency/read/1node📈 view plot
🚷 view threshold
42,429.00 ns
(+122.12%)Baseline: 19,101.52 ns
67,454.06 ns
(62.90%)
Raft_1Node_Latency/remove/1node📈 view plot
🚷 view threshold
401,520.00 ns
(-30.28%)Baseline: 575,929.22 ns
2,322,082.30 ns
(17.29%)
Raft_1Node_Latency/write/1node📈 view plot
🚷 view threshold
422,520.00 ns
(-29.22%)Baseline: 596,936.41 ns
2,150,781.11 ns
(19.64%)
build_snapshot/default📈 view plot
🚷 view threshold
116,530.00 ns
(+5.61%)Baseline: 110,339.53 ns
162,487.45 ns
(71.72%)
fernet token/project📈 view plot
🚷 view threshold
1,426.90 ns
(+3.34%)Baseline: 1,380.77 ns
1,636.39 ns
(87.20%)
get_data_keyspace📈 view plot
🚷 view threshold
0.31 ns
(+0.47%)Baseline: 0.31 ns
0.36 ns
(86.39%)
get_db📈 view plot
🚷 view threshold
0.31 ns
(-0.34%)Baseline: 0.31 ns
0.36 ns
(85.80%)
get_fernet_token_timestamp/project📈 view plot
🚷 view threshold
141.72 ns
(-1.23%)Baseline: 143.49 ns
181.02 ns
(78.29%)
get_keyspace📈 view plot
🚷 view threshold
4.40 ns
(-8.79%)Baseline: 4.83 ns
9.76 ns
(45.13%)
🐰 View full continuous benchmarking report in Bencher

@gtema gtema force-pushed the claude/adr-0025-implementation-plan-adh5ii branch 2 times, most recently from 2fe1fb6 to 9535fe9 Compare July 3, 2026 16:59
Sequences the WASM plugin work into independently-mergeable phases
(runtime foundation, full_auth mode, mapping mode, route mode, admin
APIs), pinning implementation choices the ADR left open: a dedicated
dynamic-plugin-runtime crate, a Rust reference test plugin, and
mode-by-mode phasing with admin APIs deferred to the final phase.

Complete ADR 0025 Phase 0: reference plugin and resource-limit
enforcement

- crates/config: new [dynamic_plugins]/[dynamic_plugin.*] sections
  (openstack_keystone_config::dynamic_plugins) covering every field from
  ADR 0025 §5, plus config-load-time validation of the fail-loud
  invariants from §4/§5 (reserved auth-method names, mode-vs-capability
  restrictions, hard-denylisted headers, route_targets constraints,
  well-formed sha256). Wired into Config::load_all alongside the
  existing validator-derive pass.
- crates/dynamic-plugin-runtime: new crate hosting the Extism/wasmtime
  dependency in isolation from crates/core. WasmPluginRegistry loads
  each configured plugin, verifies its SHA-256 against the pinned config
  value, and compiles it with WASI disabled. A checksum mismatch or
  missing file disables only that plugin (logged, not fatal) - every
  other plugin and builtin auth method still load, per ADR 0025 §5.
- add a minimal Rust reference dynamic auth plugin (Extism PDK,
  wasm32-unknown-unknown, standalone workspace so its guest dependency
  graph never touches the shipped binary) under
  crates/dynamic-plugin-runtime/tests/fixtures/reference-plugin. It
  exposes authenticate/mapping/route stand-in entry points plus two
  resource-limit fixtures (spin, allocate_memory) for PR 0.4's tests.
  The integration test suite builds it on the fly rather than via a
  separate xtask/CI step, so it can never run against a stale artifact.
- wire fuel_limit, timeout_ms, and memory_limit_mb into the Extism
  manifest/PluginBuilder at compile time, and add LoadedPlugin::invoke()
  which instantiates a fresh extism::Plugin (and so a fresh
  wasmtime::Store) per call, matching the ADR's "isolation between
  requests" requirement. A new InvokeError type distinguishes fuel
  exhaustion, timeout, and other traps (e.g. an over-budget guest
  allocation). Five new integration tests exercise the real compiled
  reference plugin: successful authenticate round-trip, each of the
  three resource bounds independently tripping with the right error
  variant, and proof that an exhausted invocation doesn't affect the
  next call against the same loaded plugin.

Assisted-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com>
@gtema gtema force-pushed the claude/adr-0025-implementation-plan-adh5ii branch from 9535fe9 to 7224419 Compare July 3, 2026 18:00
@gtema gtema merged commit f79065a into main Jul 3, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant