Skip to content

Remove Team Token PR2.1: Host-route admission security prerequisite - #797

Merged
josue-tech-94 merged 25 commits into
feat/user-centric-runtime-access-pathsfrom
fix/host-rpc-admission-spec65
Sep 30, 2026
Merged

josue-tech-94 merged 25 commits into
feat/user-centric-runtime-access-pathsfrom
fix/host-rpc-admission-spec65

Conversation

@josue-tech-94

@josue-tech-94 josue-tech-94 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

PR2.1 — Host-route admission security prerequisite

Stack position / purpose

PR1 (#334) → PR2 (#594) → PR2.1 (this PR) → PR2.2 (#795) → PR3 → PR4

PR2 is the direct base at 2d6f34b. This prerequisite preserves Spec 65 in PR2.1: the standalone PR2 security analysis exposed 17 genuine pre-resolution non-message Host-route admission gaps assigned to this child. Those gaps predate PR #795; they are not defects introduced by its W1 change, and they are not false positives. PR2 is intentionally not independently landable until composed with this security-completion layer. PR2.2 / #795 remains the downstream Host-ref/W1 unit and is now based on this PR2.1 head.

Problem

Several non-message /rpc/hosts/:hostRef... operations could reach live Host resolution/checkpoint work without a durable request-frequency admission boundary ahead of that work. These were R0/base-equivalent relative to PR #795. Host messages were already protected by Spec 62, and artifact routes remain governed by Spec 48.

Frozen Spec 65 contract

  • One durable, verified-subject, non-message Host-RPC aggregate bucket: 300 requests per fixed 60-second window by default.
  • Configuration: CONTROL_API_HOST_RPC_ADMISSION_RL_PER_MIN; positive finite integer only.
  • Host/session/task/path and other selector rotation cannot multiply capacity; every in-scope request costs one unit.
  • Control API owns PostgreSQL-backed admission. Admission-state failure is fail-closed with typed {"error":"host_rpc_admission_unavailable"} 503.
  • Exhaustion uses canonical 429 body and Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.
  • The existing per-Host wake effect limiter remains. Stream request-frequency admission and stream concurrency remain distinct controls.
  • Host messages remain exclusively Spec 62; artifacts remain exclusively Spec 48.

Ordering

Legacy requests preserve existing authentication and scope/body precedence, then run canonical route preflight, Spec 65 admission, live resolver/authority, and effect.

V2 requests run authentication/parser gates, exact local v2 binding, canonical route preflight, remote checkpoint, strict checkpoint validation, Spec 65 admission, live authorization, destination resolution, and effect.

Deterministically invalid route input consumes zero units. Exact v2 binding precedes preflight; valid input later denied by current live authority consumes one unit. Route validation is single-sourced and its normalized result is retained for the handler. Non-Spec-65 requireScope callers retain their existing atomic behavior.

In the current PR2.2 composition, its W1 stage runs as exact local binding → canonical preflight → W1 → remote checkpoint → applicable admission → live authority/destination → effect. W1 is implemented in downstream PR2.2, not in this PR.

Scope

Covered non-message classes: wake; approval writes; session search/read/rename; model read/write; task result/cancel; activity/status/health reads; and stream opens.

Excluded: Host messages / Spec 62; artifact list/download / Spec 48; #674/W1 implementation; unrelated Control API rate-limit behavior; PR3; broad refactors.

Implementation

The implementation lineage is R27-M1 ee05bd3404d4d0744d5f00a9832507819171dc1f, pure PR2 integration 0803435a12d73730ee0035ddf9027db695c6325b, generic-limiter reconciliation 1ba67d6202e224cf792bbdd486a23b08084b18b7, R1-B1 correction d5d0b7eea1b333a0ac60dc681daa2fdbd4f27232, and R2-B1 correction e28816ba58d1fcc25573519d34513ad3b5c36377. R1-B1 shares model-selection and session-title validators between RPC Proxy preflight and MCP Host runtime validation; R2-B1 keeps title validation on rename while context-breakdown remains path-only. The current diff from accepted PR2 contains 62 files, including canonical hook-generated version/lock and release-manifest coordinates.

Test / security proof

  • Producer-backed accepted-PR2 RED demonstrated missing pre-resolution admission on representative legacy and v2 operations; setup failures were not counted as RED.
  • R1-B1 is closed locally in d5d0b7eea1b333a0ac60dc681daa2fdbd4f27232: shared model/title validation rejects deterministic invalid input before admission/checkpoint/resolver work. Mounted tests prove legacy invalid model/title requests return 400 with zero admission/resolver calls; valid v2 binding plus invalid title returns 400 before checkpoint/admission/resolver; invalid signed model target remains invalid_binding before preflight. Bypassing canonical title preflight turns the permanent mounted assertion RED (expected 400, observed 403). Exact local binding denial retains precedence and valid input later denied by live authority still consumes admission.
  • N/N+1, selector-rotation resistance, independent-subject behavior, and fail-closed storage paths are covered by the implementation tests.
  • Host-message Spec 62 and artifact Spec 48 non-regression are covered; stream request frequency remains separate from concurrency.
  • A temporary checkpoint-before-preflight mutation made the invalid-input ordering assertion fail; the mutation was restored.
  • Local Real PostgreSQL proof was unavailable; no mock or skipped test is represented as database evidence.

Local validation

  • Control API after PR2 synchronization: 530 files; 6,634 tests passed, 416 skipped; build passed.
  • RPC Proxy after R1-B1 and R2-B1: 56 files; 697 tests passed; build passed. The four affected mounted suites passed 111/111.
  • MCP Host after R1-B1: 403 files; 4,810 tests passed, one existing todo; build passed.
  • Desktop at the original Spec 65 head: Electron verification, 74 focused tests, and main/renderer build passed. After parent sync, exact-head CI 36087548373 passed Desktop job 107922683723.
  • Shared contracts after R1-B1: 12 tests and build passed.
  • Release/version validation, release-coordinate tests, changed-file format/style, and git diff --check passed.
  • R1-B1 code review: SAFE. Security review: SAFE. Bounded collateral: CLEAN.
  • Local Real PostgreSQL was unavailable because the supported admin DSN was not configured. Exact-head CI Real PostgreSQL is required before acceptance.

Recovered linear exact-head status

  • Current published head: c869d9f1a70752ff29cb3958790cd26e7e218a09, based on PR2
    Remove Team Token PR2: Runtime actions use validated access paths #594 at 2d6f34b4021a994afd38033192fcde6885ea0204. PR2 is based on PR1
    3a9d2d1dc75d79800e5847df5c19dd97e9c68961, whose base is frozen latest
    dev 21050a2abc459e6c3a8441c024187eb3e3987f04.
  • The PR2.1 layer was reconstructed linearly on the synchronized PR2 parent;
    the downstream PR2.2 head is 0fbfc9a3aa00ea878f4c2698cb8f61a692ebcb27.
    Remote bases and ancestry agree; the complete stack has zero merge commits
    from the frozen dev snapshot.
  • R3-B1, R3-H1, R3-M1–M7, and R3-L1 remain closed. The current PR diff has
    62 files. Spec 65 still covers the 17 genuine standalone-PR2 admission gaps;
    messages remain Spec 62 and artifacts remain Spec 48.
  • Exact-head CI 36480967121, including Real PostgreSQL job
    109126211249, passed. CodeQL 36480966777 / Analyze
    109126210790 passed, and required GHAS 109133412086 passed with zero
    annotations. The required result reports no new alerts in code changed by
    this PR.
  • The old branch alert objects 1522–1539 are historical/stale on this rewritten
    branch; no current changed-code alert remains for this head. No alert was
    dismissed or otherwise changed in this sync.
  • Bounded R3 code/security/collateral reviews remain SAFE / SAFE / CLEAN. Round 4 received No
    objection at current head c869d9f1a70752ff29cb3958790cd26e7e218a09; this carries forward the
    semantic acceptance for the synchronized layer. GitHub still marks this PR REVIEW_REQUIRED,
    so human approval remains outstanding. No GitHub review or approval was published by this task.
  • rpc-proxy: host JWT hostRefs and wildcard hostRef checks are inconsistent across host routes #674 and external-rest-api: forward control-api 5xx status and Retry-After instead of answering 500 #801 remain open pending landing; control-api: rate-limit POST /admin/auth/login and POST /admin/auth/setup #800 remains deferred. PR3 has
    not started. Effective deployment configuration remains a deployment-only
    verification gate.

Historical exact-head status (superseded by the current exact-head status above)

Issue #801 remains a verified inherited pre-PR3 behavior from PR1; its lifecycle remains open pending coordinated landing in dev.

The current published head is e28816ba58d1fcc25573519d34513ad3b5c36377 on accepted PR2 base 0b40a4301d2c1fa459135c240e66c39497451022. The prior head 2ed638a003a297a94d5302540a9e2d6be63f4646 CI and CodeQL/GHAS results remain historical.

The intermediate head d5d0b7e CI run 36086705879 failed RPC Proxy job 107920095814; its Real PostgreSQL job 107920095256 succeeded. R2-B1 corrected the misplaced rename validator in e28816b. Current-head CI 36087548373 passed all jobs, including Real PostgreSQL 107922683455. CodeQL run 36087657660 / Analyze 107923015181 succeeded for branch fix/host-rpc-admission-spec65, ref refs/heads/fix/host-rpc-admission-spec65, and SHA e28816b, category /language:javascript-typescript; uploaded analysis 1837033301. Required CodeQL check 107927008949 succeeded with zero annotations and reports no new alerts in code changed by this PR. Existing branch-wide alerts were not dismissed in this pass.

Prior-head exact gate history (historical only): CI 36011314158 succeeded, including Shell syntax 107672448732, Real PostgreSQL 107672448891, Control API 107672449786, RPC Proxy 107672449461, Desktop 107672449429, shared action-context contracts 107672449650, and repository hygiene 107672448804; the reported matrix was green. CodeQL 36011521542 / Analyze 107673169072 succeeded for fix/host-rpc-admission-spec65, ref refs/heads/fix/host-rpc-admission-spec65, category /language:javascript-typescript. Required check 107680576170 succeeded. Alert 1521 (js/request-forgery, Critical) at rpc-proxy/src/routes/rpcHostProgressStream.ts:110-120 was individually dismissed as a structural false positive after fixed-destination, producer-backed validation and mutation evidence. Alerts 1522–1539 were not generated changed-code annotations and were not dispositioned. All of this applies only to prior head 2ed638a003a297a94d5302540a9e2d6be63f4646, not current acceptance.

For older history, CodeQL workflow 35956661657 succeeded at ee05bd3404d4d0744d5f00a9832507819171dc1f, but required check 107500130065 failed on a critical SSRF annotation at rpc-proxy/src/routes/rpcHostProgressStream.ts:110-120. That old-head alert remains historical/unadjudicated and is not current evidence.

At that historical stage, PR2.1 was not accepted, merged, or landed and its Round 2 formal review was pending; the current status above supersedes that snapshot.

Landing / stack sequence

  1. Obtain the required GitHub human approval for this PR and PR2.2 Remove Team Token PR2.2: Host-ref authority and validation #795.
  2. Use the recovered linear stack for the coordinated pre-PR3 landing review; deploy schema/Control API before the Spec65-enabled RPC Proxy and keep all client activation gates off.
  3. Keep external-rest-api: forward control-api 5xx status and Retry-After instead of answering 500 #801 and rpc-proxy: host JWT hostRefs and wildcard hostRef checks are inconsistent across host routes #674 open pending landing. No PR3 work begins before coordinated landing and post-landing verification.

@josue-tech-94 josue-tech-94 changed the title feat(control-api): add subject-wide Host RPC admission Remove Team Token PR2.1: Host-route admission security prerequisite Sep 24, 2026
@josue-tech-94
josue-tech-94 force-pushed the fix/host-rpc-admission-spec65 branch from 5f3bd3c to 2bfe0b8 Compare September 25, 2026 19:28
@alfredolopez80

Copy link
Copy Markdown
Contributor

PR Review — Remove Team Token PR2.1: Host-route admission security prerequisite (Spec 65)

Review verdict

NO — a merge blocker and confirmed regressions remain.

Reviewed the complete diff at base b311ff9 (PR594 head) → head 2bfe0b8 (57 files, +2,416/−451) in disposable exact-head worktrees with independent exploration/ordering, implementation, and security lanes.

PR-introduced issue count

  • Blocker/Critical: 1
  • High: 1
  • Medium: 6 (five confirmed, one likely)
  • Low: 2
  • Pre-existing: 0
  • Uncertain/unavailable: 1 (Transfer-Encoding stream-body behavior reasoned from HTTP semantics, not runtime-reproduced)
  • Root-cause clusters: 4

Findings

RP797-001 — Blocker — deploy/base/control-plane/configmaps.yaml:216

The Minikube rpc-proxy sends Host-RPC admission through control-api-rpc-gateway (RPC_PROXY_CONTROL_API_BASE_URL, overlay line 33), but the gateway allowlist regex ^/api/v1/rpc/access/users/[^/]+/mcp-hosts/[^/]+$ does not match the suffixed .../mcp-hosts/:hostRef/host-rpc-admission. The path falls through to location / { return 403; } and the transport surfaces {error:"Forbidden"}, so every valid legacy Host-RPC request fails before any Host effect. No deploy file contains host-rpc-admission — or action-authority/checkpoint, which also affects the v2 paths staged through the same base URL.

This is not a dormant-v2 issue: the stack reviewer context itself lists Spec 65 non-message Host-RPC admission as active immediately after landing, and the affected adapter is the legacy one. In the configured deployment this breaks active legacy Host-RPC traffic, not just future v2 flows. The documented rollout order (migrations → Control API → Spec-65-enabled RPC Proxy) is correct but does not help here, because the missing gateway location is part of this PR's own deployment surface.

  • Remedy: add exact POST-only locations for admission and checkpoint (or a dedicated service-token Control API base URL), plus a static deploy-contract test comparing called Control API paths against each overlay's gateway allowlist. The order tests mock requestHostRpcAdmission, which is why this stayed green.

RP797-002 — High — rpc-proxy/src/hostRpcPreflight.ts:105

A deterministically malformed sessions cursor (e.g. cursor=not-a-cursor) passes preflight — which only checks non-empty string ≤2048 bytes — consumes one admission unit, reaches Host resolution, and only then mcp-host returns 400 Invalid sessions cursor. Violates the zero-charge contract for deterministic invalid input. Remedy: share a canonical cursor validator between proxy preflight and mcp-host, and add the missing order test.

RP797-003 — Medium — control-api/src/routes/rpc-access/users.ts:279

The new legacy admission endpoint's scope allowlist omits host:wake:write, while POST /rpc/hosts/:hostRef/wake requires exactly that scope before calling it. A valid wake-only (least-privilege) token gets 403 at the admission endpoint. Remedy: add the scope and cover a wake-only token across the proxy→Control API boundary.

RP797-004 — Medium — rpc-proxy/src/services/controlApiRestService.ts:124

A malformed upstream 429 missing X-RateLimit-Remaining passes legacy response validation because Number(null) === 0 (verified), and the proxy forwards the header as the literal string "null" instead of mapping to typed 503. Remedy: require header presence and canonical decimal syntax (0) before forwarding.

RP797-005 — Medium — rpc-proxy/src/hostRpcPreflight.ts:259

Canonical preflight does not validate activity query input: limit=-1 or limit=abc passes, charges admission, and is silently normalized/clamped after admission. Additionally, the task-progress-stream branch lost the base */% hostRef rejection that status/activity stream branches retain. Remedy: positive-integer limit validation in preflight; apply the wildcard/percent rule to the task branch.

RP797-006 — Medium (likely) — rpc-proxy/src/hostRpcPreflight.ts:59

The read-only stream body guard checks only Content-Length; a body framed with Transfer-Encoding: chunked and no Content-Length bypasses the canonical preflight and consumes admission. Remedy: reject a truthy transfer-encoding header as well.

RP797-007 — Medium — control-api/src/services/rateLimiterService.ts:88

Strict admission DB failures are caught and converted to typed 503 without the existing rate_limit_backend_errors_total metric or rate_limit_db_error structured log — only the fail-open generic path instruments errors, and the Spec-62 host-message refactor onto the strict path inherits the telemetry loss. Remedy: factor the instrumented catch into a shared helper that records and rethrows for strict callers.

RP797-008 — Medium (likely) — packages/action-context-contracts/index.cjs:49

The new proxy preflight normalizes and Array.from()s the entire raw rename title before enforcing the 120-code-point limit; with the 10 MB body ceiling, repeated authenticated oversized titles allocate large arrays on the public proxy without ever consuming the aggregate budget. Remedy: bound raw title processing before full normalization, with an explicit compatibility decision for oversized text that would normalize short.

RP797-009 — Low — rpc-proxy/src/routes/rpc.ts:1414

Task result/cancel 404 body text changed to "Forbidden: user cannot access this host" instead of the base anti-enumeration text "Host not found or not accessible". Wire-message only.

RP797-010 — Low — rpc-proxy/src/hostRpcPreflight.ts:108

Two 400 messages/precedence changed for the sessions list/messages routes when multiple dimensions are invalid. No admission impact.

Root-cause clusters

  • Deployment-transport (001): app routes added without a gateway allowlist update; no static deploy-contract test.
  • Preflight completeness (002, 005, 006): canonicalization moved shape checks forward but not semantic validators (cursor, limits, wildcard, framing).
  • Admission-contract alignment (003, 004, 009, 010): endpoint scope list and transport validation drifted from route contracts.
  • Observability/resource bounds (007, 008): fail-closed paths lost telemetry; pre-admission work unbounded.

Verified clean

  • Ordering verified for all 18 Spec-65 route patterns (legacy: auth/scope/body → preflight → admission → resolver → effect; v2: auth/parser → binding → preflight → checkpoint → strict validation → admission → live auth → destination). Messages (Spec 62) and artifacts (Spec 48) correctly excluded; each in-scope request charges exactly once; invalid shared model/title input rejects before admission/checkpoint/resolver.
  • Bucket key is subject-only (host-rpc-admission:<verifiedSubject>); host/session/task/path selectors cannot rotate capacity; independent subjects verified.
  • PostgreSQL primitive: one atomic INSERT ... ON CONFLICT ... RETURNING count with a composite PK; missing rows throw; strict callers have no process-memory fallback; boundary math (N/N+1, remaining clamp, reset, Retry-After ≥ 1 s) is correct; config parsing rejects zero/negative/fractional/hex/exponential/Infinity/unsafe values.
  • Streams: admission on open only; concurrency caps untouched; Desktop honors Retry-After (progress tested; status/activity share the helper).
  • Model-selection and session-title validators are shared between rpc-proxy preflight and mcp-host through @clerum/action-context-contracts; context-breakdown remains path-only; messages remain on the Spec-62 receipt path.

Limitations

Static review only; the gateway denial is reasoned from the exact deployed config (regex + fallback + absent route names all verified) rather than reproduced on a live cluster. Window timestamps use the Control API app clock — acceptable at the current single replica; a multi-replica scale-out needs a DB-clock/coordination decision. Parent PR594 blockers remain: even with this PR fixed, the v2 chat chain stays broken at issuance/checkpoint/gateway in the parent, so the stack should be fixed base-first.

josue-tech-94 and others added 16 commits September 29, 2026 20:16
Add a durable verified-subject budget before protected Host-RPC work. The
same 300-per-fixed-minute bucket is shared by legacy adapters and v2
checkpoints; Host messages and artifacts retain their existing policies.

- Add strict PostgreSQL fixed-window admission and a narrow legacy adapter.
- Charge the closed v2 non-message operation set before live authorization.
- Add canonical request-local route preflight before checkpoints and admission.
- Keep exact local binding and remote checkpoint as separate reused stages.
- Preserve stream concurrency and honor Retry-After on reconnects.

Class-check: Spec 65 Host-RPC preflight/admission registrations -> 18 sites;
all 18 non-message routes use staged preflight; messages remain Spec 62 and
artifact list/download remain Spec 48.

- Control API: 511 files, 6,163 tests passed; 365 skipped; build passed.
- RPC Proxy: 56 files, 693 tests passed; build passed.
- Desktop: Electron verified; 74 focused tests and full build passed.
- Action-context contracts: 11 tests and build passed.
- Code review SAFE; security review SAFE; collateral CLEAN.
- Local Real PostgreSQL DSN unavailable; exact-head CI Real-PG is required.
- Changed-file Prettier, style-rules, and git diff --check passed.

- Fixed-window boundary bursts are accepted by Spec 65.
- Exact-head Real PostgreSQL remains a publication acceptance gate.
Keep generic #766 backend-unavailable results separate from strict Spec 65 admission.

Both paths use one bounded, rateLimitPool-backed fixed-window SQL primitive.

Class-check: generic pool, strict callers, cleanup, and limiter tests.
Share model and rename validators across RPC Proxy and MCP Host.

Reject deterministic invalid input before admission, checkpoint, or resolver work.

Class-check: Spec 65 model writes and session renames on legacy and v2 paths.

Repro-test: buggy head 1ba67d6 returned 403 after

admission → live-resolver for an invalid legacy rename; the permanent assertion is green.
Class-check: shared session-title preflight across context-breakdown and rename;

validate only rename while context-breakdown remains path-only.

Repro-test: exact-head CI at d5d0b7e failed nine RPC Proxy assertions; focused

mounted suites now pass 111/111 and the full suite passes 697/697.

R2-B1: restore context-breakdown behavior and retain canonical rename validation.
Class-check: approval ID fallback -> 2 routes -> both preflight before admission; v2 binding first.

Repro-test: rpc-proxy/src/__tests__/host-rpc-admission-order.producer.test.ts

fails at e28816b (400 expected, 403 observed).
Class-check: host-rpc-admission gateway routes -> 1 production location -> exact POST only.

Default deny is preserved; no broad internal route is exposed.

Repro-test: scripts/tests/test-mcp-host-action-checkpoint-gateway.sh fails at 36085ac with the expected missing exact admission location, then passes after correction.
Class-check: host-rpc-admission scope allowlist -> 1 route registration -> include the required wake scope while preserving all other scope checks.

Repro-test: control-api/test/hostRpcAdmissionCheckpoint.test.ts fails at 2d87246 (204 expected, 403 observed).
Class-check: Host-RPC admission 429 header coercions -> 4 headers -> require explicit canonical numeric values for each allowlisted field.

Repro-test: rpc-proxy/src/__tests__/host-rpc-admission-transport.test.ts fails at d5a2826 (missing/hex values returned 429 instead of typed 503).
Class-check: sessions cursor decode/scope implementations -> 1 canonical contract and 2 consumers -> share one parser across MCP Host and RPC Proxy.

Repro-test: rpc-proxy/src/__tests__/host-rpc-admission-order.producer.test.ts fails at c87a378 (malformed cursor returned 403 after admission instead of the existing 400).
Class-check: Host activity limit parsing in RPC Proxy and MCP Host -> 2 boundaries -> use one shared positive-finite validator and retain the validated value.

Repro-test: rpc-proxy/src/__tests__/host-rpc-admission-order.producer.test.ts fails at ea2764f (invalid limits charged admission and reached Host resolution).
Class-check: Host-ref preflight checks -> 8 route classes -> apply the existing safe path rule and wildcard/percent rejection to task progress streams; leave other route policies unchanged.

Repro-test: rpc-proxy/src/__tests__/host-rpc-admission-order.producer.test.ts fails at 713a4f1 (invalid refs reached admission and resolver, returning 403 instead of 400).
Class-check: strict admission uses checkAndIncrementStrict; generic callers keep their existing fallback.

Repro-test: test/services.rateLimiter.test.ts fails at a5604b3 because strict store failure records no metric/log.
Class-check: session-message Host, agent, and chat path identity are checked before pagination; valid paths retain the pagination error.

Repro-test: host-rpc-admission-order.producer.test.ts fails at d90830a because a malformed Host path plus limit returns the pagination error instead of the established path error.
Class-check: status, activity, and progress read-only stream preflight all use the shared body guard; reject any transfer-encoded request body before admission.

Repro-test: host-rpc-admission-order.producer.test.ts fails at a15e0fa because a raw chunked GET without Content-Length reaches admission and live Host resolution instead of the established 400.
Class-check: normalize first, then preserve the 120-code-point/512-byte title contract; reject normalized UTF-16 length above 240 before allocating an unbounded code-point array. No raw-length cutoff.

Repro-test: action-context-contracts/index.test.cjs fails at 1368c8f because the 121-code-point title calls Array.from instead of taking the bounded fast path.
Class-check: valid passthrough cursor fixtures use the shared producer; malformed cursors stay 400.

Repro-test: passthrough.test.ts fails at cb4038d: literal cursor current is rejected.

The stale fixture gets 400 instead of its expected 200 forwarding response.
Reconcile the replayed child tree to the explicit three-way integration oracle.
@josue-tech-94
josue-tech-94 force-pushed the fix/host-rpc-admission-spec65 branch from c869d9f to 65182d3 Compare September 30, 2026 02:29
josue-tech-94 and others added 5 commits September 29, 2026 20:37
Stable-ID: R27-M1

Class-check: /rpc/hosts/:hostRef public class -> 21 registrations -> one shared W1 validator
covers all 21; Desktop and internal Control API routes remain outside Spec 61.

Repro-test: mounted invalid_host assertions fail on 18/20 legacy-capable registrations at
730a6eb; both artifact registrations were
already-400 positive controls.
Separate the existing local v2 route binding from remote checkpoint execution

for the 21 Spec 61 Host-ref routes so shared W1 validation runs between

them. Non-Host v2 callers retain the original checkpoint path.

Class-check: requireScope calls in the 21 Host-ref registrations -> 21 sites -> all defer only the remote checkpoint until after shared W1; non-Host callers remain unchanged.

Repro-test: rpc-proxy/src/__tests__/host-ref-validation.test.ts rejects a producer-signed target with a whitespace Host ref before checkpoint I/O; RED at 490b0e3.
Class-check: w1PayloadRoutes in host-ref-validation.test.ts → 4 route classes
(approval approve/deny, model write, session rename). Valid bodies exercise W1;
valid-host controls cover all four. Malformed-body precedence remains separate
under Spec 61.

Repro-test: rpc-proxy/src/__tests__/host-ref-validation.test.ts:197
(fails at 6173730 when W1 is bypassed; each
assertion expects exact 400 but receives the downstream result).
@josue-tech-94
josue-tech-94 merged commit f52c984 into dev Sep 30, 2026
167 of 169 checks passed
@josue-tech-94
josue-tech-94 deleted the fix/host-rpc-admission-spec65 branch September 30, 2026 03:48
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.

2 participants