|
408 | 408 | {"id":"oracle-qmwz.2.9.2","title":"P1-9b — OAuth 2.1 resource-server token validation (RFC 9728/8707/9207, PKCE)","description":"Subtask. Approach: OAuth 2.1 RESOURCE SERVER only (validate, never issue) via tower-oauth2-resource-server + jsonwebtoken; RFC 9728 protected-resource metadata at /.well-known/oauth-protected-resource; PKCE S256; RFC 8707 resource indicators + RFC 9207 iss validation. OWN/WRAP the auth edge ourselves. Success: valid token passes, expired/wrong-audience rejected. Test: integration token matrix. Considerations: highest-CVE surface (R12); pin rmcp, track advisories.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-06-01T13:34:19.588480369Z","created_by":"durakovic","updated_at":"2026-06-01T20:24:50.203250522Z","closed_at":"2026-06-01T20:24:50.203025572Z","close_reason":"OAuth 2.1 resource-server token validation, now ENFORCED on the transport (P1-9b). The validation library (oraclemcp-auth::oauth_rs, committed earlier) does real HS256 JWT verify (HMAC over sha2, KAT-tested), issuer allowlist, RFC 8707 audience binding, exp/nbf, scope subset, alg=none rejection, RFC 9728 protected_resource_metadata + WWW-Authenticate, with a SignatureVerifier seam for RS256/ES256 via JWKS — 12-case token matrix. NOW WIRED into the Streamable HTTP transport (2.9.1): oraclemcp-core::http::oauth_guard is an axum middleware layered on /mcp that extracts the bearer token, calls ResourceServerConfig.validate(token, verifier, now), and on failure returns 401 + WWW-Authenticate (RFC 9728 resource_metadata + invalid_token/insufficient_scope error code); the /.well-known/oauth-protected-resource metadata route stays OPEN for authorization-server discovery. Valid tokens pass + their scopes are attached as ScopeGrant request extensions (feeds P1-9e scope->ceiling). OWN/WRAP the auth edge ourselves; highest-CVE surface kept small + audited; cargo-deny advisories OK on the new HTTP dep tree. Tests: 12 oauth_rs matrix cases + 4 transport enforcement (missing-token->401+challenge, bad-token->401, metadata-stays-open). clippy -D warnings, fmt, boundary OK.","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.2.9.2","depends_on_id":"oracle-qmwz.2.9","type":"parent-child","created_at":"2026-06-01T13:34:19.588480369Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.2.9.2","depends_on_id":"oracle-qmwz.2.9.1","type":"blocks","created_at":"2026-06-01T13:34:20.327455690Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
409 | 409 | {"id":"oracle-qmwz.2.9.3","title":"P1-9c — TLS + mTLS (rustls), HTTPS-only","description":"Subtask. Approach: TLS/HTTPS-only via rustls; mTLS as defense-in-depth. Success: HTTP rejected, HTTPS works, mTLS handshake enforced when configured. Test: integration TLS/mTLS handshake. Considerations: reject non-loopback http:// (see P1-9d).","status":"open","priority":1,"issue_type":"task","created_at":"2026-06-01T13:34:19.760901058Z","created_by":"durakovic","updated_at":"2026-06-01T13:34:20.544165547Z","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.2.9.3","depends_on_id":"oracle-qmwz.2.9","type":"parent-child","created_at":"2026-06-01T13:34:19.760901058Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.2.9.3","depends_on_id":"oracle-qmwz.2.9.1","type":"blocks","created_at":"2026-06-01T13:34:20.543188553Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
410 | 410 | {"id":"oracle-qmwz.2.9.4","title":"P1-9d — Origin checks / DNS-rebinding guard / reject non-loopback http","description":"Subtask. Approach: validate Origin; DNS-rebinding guard; reject non-loopback http://. These are known rmcp HTTP failure modes. Success: rebinding/bad-origin requests rejected. Test: integration with crafted Origin/host. Considerations: part of front-loaded HTTP hardening (R12).","status":"closed","priority":1,"issue_type":"task","created_at":"2026-06-01T13:34:19.939816116Z","created_by":"durakovic","updated_at":"2026-06-01T19:27:12.021512723Z","closed_at":"2026-06-01T19:27:12.021283238Z","close_reason":"Implemented HTTP transport hardening guard (P1-9d). oraclemcp-auth::http_guard adds HttpGuardPolicy{allowed_origins, allowed_hosts, allow_non_loopback_http} + check(scheme, host_header, origin) -> Result<(), HttpGuardError> enforcing the three known rmcp local-HTTP failure modes (MCP spec 2025-11-25, risk R12): (1) DNS-rebinding guard — Host header required (MissingHost) and must be loopback or operator-allowlisted, else UntrustedHost (a rebinding request carries the attacker hostname in Host); (2) reject non-loopback http:// (NonLoopbackHttp) unless allow_non_loopback_http opt-in (same-host TLS-terminating proxy); (3) Origin check — loopback origins always allowed, others must be allowlisted else ForbiddenOrigin (omitted Origin allowed for non-browser MCP clients). authority_is_loopback() + host_only() correctly parse host:port and bracketed IPv6 ([::1]:443). Transport-agnostic pure logic the axum/rmcp transport (P1-9a) calls per request before dispatch. 8 tests (loopback http ok, non-loopback http rejected/opt-in, DNS-rebinding Host rejected, allowlisted host passes incl port-insensitive, missing Host rejected, cross-origin rejected vs allowlisted, loopback origin always ok). clippy -D warnings, fmt, boundary OK.","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.2.9.4","depends_on_id":"oracle-qmwz.2.9","type":"parent-child","created_at":"2026-06-01T13:34:19.939816116Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
411 | | -{"id":"oracle-qmwz.2.9.5","title":"P1-9e — Progressive scope -> operating-level ceiling mapping (scope can only LOWER)","description":"Subtask. Approach: scopes oracle:read->execute->admin map to the operating-level ceiling and are challenged via WWW-Authenticate; an OAuth scope can only LOWER the effective ceiling, never raise it past the profile max_level. Success: an oracle:read token cannot invoke a write tool. Test: integration scope enforcement. Considerations: composes with RBAC (P2-4) and the per-target max_level (P0-7).","status":"open","priority":1,"issue_type":"task","created_at":"2026-06-01T13:34:20.108875616Z","created_by":"durakovic","updated_at":"2026-06-01T13:34:20.766921264Z","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.2.9.5","depends_on_id":"oracle-qmwz.2.9","type":"parent-child","created_at":"2026-06-01T13:34:20.108875616Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.2.9.5","depends_on_id":"oracle-qmwz.2.9.2","type":"blocks","created_at":"2026-06-01T13:34:20.766325908Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
| 411 | +{"id":"oracle-qmwz.2.9.5","title":"P1-9e — Progressive scope -> operating-level ceiling mapping (scope can only LOWER)","description":"Subtask. Approach: scopes oracle:read->execute->admin map to the operating-level ceiling and are challenged via WWW-Authenticate; an OAuth scope can only LOWER the effective ceiling, never raise it past the profile max_level. Success: an oracle:read token cannot invoke a write tool. Test: integration scope enforcement. Considerations: composes with RBAC (P2-4) and the per-target max_level (P0-7).","status":"closed","priority":1,"issue_type":"task","created_at":"2026-06-01T13:34:20.108875616Z","created_by":"durakovic","updated_at":"2026-06-01T20:25:05.401981723Z","closed_at":"2026-06-01T20:25:05.401686114Z","close_reason":"Progressive scope -> operating-level ceiling mapping, scope can only LOWER (P1-9e). The mapping is fully implemented + tested in oraclemcp-auth::scope: scope_to_level (oracle:read->ReadOnly, oracle:write/execute->ReadWrite, oracle:ddl->Ddl, oracle:admin->Admin), scopes_ceiling (highest recognized scope, defaulting to the READ_ONLY safe floor), apply_oauth_scopes (lowers the effective ceiling to min(profile max_level, scope ceiling) — MONOTONE-DOWN, never raises it past max_level). 5 tests incl scope_can_only_lower_the_ceiling (a later higher scope cannot raise it back) and read_scope_blocks_a_write_at_the_gate (an oracle:read token -> a write (ReadWrite) is HARD-BLOCKED at the gate via SessionLevelState.evaluate -> LevelDecision::Blocked, a read is Allowed) — the success criterion 'an oracle:read token cannot invoke a write tool'. Composes with RBAC (P2-4) + the per-target max_level (P0-7). Now end-to-end: the OAuth RS layer (2.9.2) validates the token and yields its scopes via WWW-Authenticate-challenged auth; oraclemcp-core::http::oauth_guard attaches the validated scopes as a ScopeGrant request extension which the session-setup layer applies via apply_oauth_scopes to lower the ceiling. clippy -D warnings, fmt, boundary OK.","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.2.9.5","depends_on_id":"oracle-qmwz.2.9","type":"parent-child","created_at":"2026-06-01T13:34:20.108875616Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.2.9.5","depends_on_id":"oracle-qmwz.2.9.2","type":"blocks","created_at":"2026-06-01T13:34:20.766325908Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
412 | 412 | {"id":"oracle-qmwz.3","title":"OMCP Phase 2 — Production hardening (the gate to fully safe-for-production)","description":"PHASE 2 EPIC — production hardening. NOT deferred-forever; it is dependency-ordered (it builds on the Phase 1 core). These are the items that move v1 from \"great core\" to \"safe to point at a shared/production DB\".\n\n## Scope (tasks)\nP2-1 admission control / backpressure (semaphore + per-agent caps + fair queue + structured BUSY); P2-2 cancellation + graceful shutdown + crash rollback; P2-3 execute-in-savepoint preview + transaction/savepoint/DBMS_OUTPUT tools; P2-4 RBAC per tool (scope->max_level) + session-elevation windows + replay-hardening; P2-5 Vault secrets backend; P2-6 OTel metrics/traces; P2-7 Tier-2 PL/Scope intelligence + recompile_with_plscope; P2-9 privilege-degradation matrix + capability reporting; P2-10 Oracle Unified Auditing policy as system-of-record. (P2-8 \"config-driven virtual tools\" was PROMOTED to Phase 1 / P1-13 — it is an adoption driver, not hardening.)\n\n## Success criteria\nThe server survives multi-agent load on a shared DB without causing incidents (no pool starvation / ORA-12519), cancels cleanly without double-executing DML, previews real blast radius, and produces an authoritative audit trail.","status":"open","priority":2,"issue_type":"epic","created_at":"2026-06-01T13:24:54.034744121Z","created_by":"durakovic","updated_at":"2026-06-01T13:24:54.034744121Z","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.3","depends_on_id":"oracle-qmwz","type":"parent-child","created_at":"2026-06-01T13:24:54.034744121Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
413 | 413 | {"id":"oracle-qmwz.3.1","title":"P2-1 — Admission control / backpressure (semaphore + per-agent caps + fair queue + BUSY)","description":"## Background\nFixed pool + N agents x M concurrent calls = pool starvation + ORA-12519/ORA-00018 against a shared prod DB — the most likely way the server itself causes an incident.\n## Technical approach\nGlobal concurrency cap = pool max_size, enforced by tokio::sync::Semaphore; per-agent caps on top; a bounded FAIR queue; over budget -> structured {error:BUSY, retry_after_ms:N} BEFORE touching the pool. HTTP path adds tower-governor (GCRA) keyed by agent identity. Never let the 512-thread blocking pool be the limiter — the semaphore is.\n## Success criteria\nUnder load, excess calls get BUSY+retry-after without exhausting the pool; per-agent fairness holds.\n## Test plan\n- Chaos: pool exhaustion returns BUSY, not ORA-12519; per-agent cap enforced.\n## Considerations\nThis is the backbone of safe multi-agent HTTP sharing.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-06-01T13:30:40.232696237Z","created_by":"durakovic","updated_at":"2026-06-01T18:37:26.207906502Z","closed_at":"2026-06-01T18:37:26.207613975Z","close_reason":"P2-1 admission control / backpressure (oraclemcp-core admission.rs, §5.6). AdmissionController bounds concurrency BEFORE the pool is touched: a global cap (= pool max_size) + a per-agent cap, both via tokio::sync::Semaphore (try_acquire_owned, non-blocking). try_admit(agent) takes the per-agent permit FIRST (a noisy agent hits its own cap before starving the global pool), then the global permit; over budget returns a structured OracleMcpError::Busy{retry_after_ms} (-> BUSY envelope, retry_after) rather than queueing unboundedly. AdmissionPermit (RAII) returns both permits on drop. The semaphore, never the 512-thread blocking pool, is the limiter. 4 tests: admits-to-global-cap-then-busy + release re-admits; per-agent-cap isolates a noisy agent (other agents unaffected); busy-envelope carries retry_after; permit release restores capacity. clippy -D warnings + fmt clean.","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.3.1","depends_on_id":"oracle-qmwz.1.4","type":"blocks","created_at":"2026-06-01T13:30:41.409300310Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.3.1","depends_on_id":"oracle-qmwz.3","type":"parent-child","created_at":"2026-06-01T13:30:40.232696237Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
414 | 414 | {"id":"oracle-qmwz.3.10","title":"P2-RES — MCP Resources + Prompts (oracle:// scheme + expert prompt playbooks)","description":"## Background\nTools alone are a gap (the completeness critic's \"tools-only\" finding). Resources make the server browsable; Prompts ship discoverable expert playbooks any harness can list. Resources land in P2 (v1 discovery uses oracle_capabilities).\n## Technical approach\n- Resources with a coherent scheme: oracle://schema/{owner} (object listing), oracle://object/{owner}/{type}/{name} (DDL/source), oracle://session/{lease_id} (live session state), oracle://capabilities, oracle://tools (the virtual-tool catalog — P1-13). Cursor pagination; resources/list_changed + resources/updated where feasible (e.g. DDL change via DBMS_CHANGE_NOTIFICATION).\n- Prompts (parameterized recipes): investigate_slow_query, safe_column_rename, explain_this_package, find_callers_of, generate_migration.\n## Success criteria\nA client lists resources + prompts; oracle://object returns DDL; a prompt produces a usable recipe.\n## Test plan\n- e2e: resources/list + read; prompts/list + get; pagination cursor.\n## Considerations\nBonus where the client supports them; tools never depend on them. Depends on rmcp (P0-6) + Tier-1 intelligence (P1-5) for content.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-06-01T13:56:11.181654587Z","created_by":"durakovic","updated_at":"2026-06-01T19:55:27.711993661Z","closed_at":"2026-06-01T19:55:27.711771099Z","close_reason":"Implemented MCP Resources + Prompts (P2-RES). oraclemcp-core::resources (engine-free; one-way boundary holds): the oracle:// URI scheme model + routing — ResourceUri::parse/to_uri for oracle://capabilities, oracle://tools (the P1-13 virtual-tool catalog), oracle://schema/{owner}, oracle://object/{owner}/{type}/{name} (DDL/source), oracle://session/{lease_id}; bad/unknown URIs rejected. resource_templates() is the resources/list browsable surface (5 schemes w/ name+description+mime). read_resource() routes capabilities/tools to in-core JSON documents and schema/object/session to an injected ResourceProvider seam (engine/db supplies live content — keeps core engine-free). PROMPTS: prompt_catalog() ships 5 discoverable expert playbooks (investigate_slow_query, safe_column_rename, explain_this_package, find_callers_of, generate_migration) with typed PromptArgs; render_prompt(name,args) validates required args (missing->InvalidArguments, unknown prompt->ObjectNotFound) and produces a usable recipe (PromptMessage role+text referencing the server's tools). Resources/prompts are a bonus where the client supports them; tools never depend on them. 7 tests (URI roundtrip all 5 + bad rejected, templates cover 5, read_resource routes static+live via mock DDL provider, catalog lists 5 playbooks, render produces recipe w/ interpolated sql, render validates args+name). clippy -D warnings, fmt, boundary OK.","source_repo":"plsql-intelligence","compaction_level":0,"original_size":0,"labels":["oraclemcp"],"dependencies":[{"issue_id":"oracle-qmwz.3.10","depends_on_id":"oracle-qmwz.1.7","type":"blocks","created_at":"2026-06-01T13:56:11.341133819Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.3.10","depends_on_id":"oracle-qmwz.2.5","type":"blocks","created_at":"2026-06-01T13:56:11.462848431Z","created_by":"durakovic","metadata":"{}","thread_id":""},{"issue_id":"oracle-qmwz.3.10","depends_on_id":"oracle-qmwz.3","type":"parent-child","created_at":"2026-06-01T13:56:11.181654587Z","created_by":"durakovic","metadata":"{}","thread_id":""}]} |
|
0 commit comments