') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); fix(governance): fail closed on integration authority outages by reprewindai-dev · Pull Request #44 · reprewindai-dev/cAPI · GitHub
Skip to content

fix(governance): fail closed on integration authority outages - #44

Closed
reprewindai-dev wants to merge 3 commits into
mainfrom
fix/fail-closed-integration-authority-cache
Closed

fix(governance): fail closed on integration authority outages#44
reprewindai-dev wants to merge 3 commits into
mainfrom
fix/fail-closed-integration-authority-cache

Conversation

@reprewindai-dev

@reprewindai-devreprewindai-dev commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Closes#43.

Rebuilt directly on current cAPI main8d6a692ecae8d239692f9b0bbb091854da6c3372, preserving the merged MCP incident remediation and docs/MCP_SECURITY_BOUNDARY.md.

Current main still allows generic postIntegration() to cache successful authority POST responses and replay them as _stale after timeout/network/5xx failure. That turns previously observed authority into current authority when CAPPO is unavailable.

This PR changes only src/lib/covenant/integrations.ts plus focused Vitest coverage. It removes authority-response caching/stale replay, preserves explicit 401/403 AuthorityDenied, and converts timeout/network/5xx/invalid-response paths to IntegrationUnavailable.

Regression coverage includes:

  • prior APPROVED followed by 503 cannot replay approval;
  • prior APPROVED followed by network rejection cannot replay approval;
  • the real three-second abort timeout fails closed;
  • 403 remains AuthorityDenied;
  • invalid success payloads fail closed.

No runtime-verification claim is made. Reported cAPI runtime remains 3003 and stays NOT_VERIFIED until deployed SHA + HTTP/protocol identity + listener + Traefik agree. Verify cAPI first after restart, then Gnomledger registration, then the public GPC routes.

Keep draft until exact-head test/lint/build/security checks actually execute and pass with no blocking review.

@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
c-apiErrorErrorAug 29, 2026 12:14am
veklom-id-59uwErrorErrorAug 29, 2026 12:14am

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
auto_review:
drafts: true
📝 Walkthrough

Walkthrough

postIntegration now fails closed when the upstream integration is unavailable or returns an invalid payload. It removes Redis success caching and stale-response fallback, preserves typed authority errors, and adds regression tests for these cases.

Changes

Integration fail-closed handling

Layer / File(s)Summary
Fail-closed postIntegration behavior
src/lib/covenant/integrations.ts
The function removes Redis caching and stale fallback. It maps non-authority failures and invalid payloads to IntegrationUnavailable, preserves authority and integration errors, and clears the timeout in finally.
Authority boundary regression coverage
tests/integrations.fail-closed.test.ts
Tests verify that upstream failures do not replay cached success, 403 remains AuthorityDenied, invalid success payloads fail, and mocks reset after each test.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score:🔵 Low · up to cf364

The integration path now fails closed for tested HTTP errors and invalid payloads, but rejected requests and timeout handling still lack regression coverage. The PR is mergeable with explicit owner follow-up to add those bounded tests.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Linked Issues check✅ PassedThe changes remove stale authority replay, preserve denial handling, fail closed on integration errors, and add focused negative tests for issue #43.
Out of Scope Changes check✅ PassedThe code and tests remain focused on integration authority caching, failure handling, and governance-boundary behavior.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly and concisely describes the main change: making integration authority handling fail closed during outages.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/fail-closed-integration-authority-cache

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

@coderabbitai review

Please review exact head cf3641f7e82332a1f5e5bc0a1fe1b73fb8d04ee0 despite draft state. Focus on fail-closed semantics: no stale authority replay, 401/403 preserved as AuthorityDenied, timeout/network/5xx/invalid responses as IntegrationUnavailable, and no regression to native MCP/CAPPO authorization. GitHub Actions on this repository are currently failing pre-execution (no runner / no steps), so this review is supplemental only and does not replace executable exact-head CI.

@coderabbitai

coderabbitaiBot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bashset -euo pipefail
expected='cf3641f7e82332a1f5e5bc0a1fe1b73fb8d04ee0'
actual="$(git rev-parse HEAD)"printf'HEAD=%s\nEXPECTED=%s\n'"$actual""$expected"
git status --short
git diff --no-ext-diff --unified=80 "${expected}^""$expected" --
printf'\n--- candidate source and test files ---\n'
fd -t f .| rg -i '(cappo|integration|mcp|authori|governance|post.*integration|vitest|test)'printf'\n--- definitions and call sites ---\n'
rg -n -i -C 4 'postIntegration\s*\(|AuthorityDenied|IntegrationUnavailable|stale|native.*mcp|mcp.*native|CAPPO' \
-g '!node_modules' -g '!dist' -g '!build'.printf'\n--- file outlines for changed source and test files ---\n'
git diff --name-only "${expected}^""$expected" -- \
|while IFS= read -r file;docase"$file"in*.ts|*.tsx|*.js|*.jsx)
echo"### $file"
ast-grep outline "$file" --items all ||true
;;
esacdone

Length of output: 126894


🏁 Script executed:

#!/bin/bashset -euo pipefail
head='cf3641f7e82332a1f5e5bc0a1fe1b73fb8d04ee0'
base="$(git merge-base "$head" origin/main 2>/dev/null || git merge-base "$head" main)"printf'MERGE_BASE=%s\n'"$base"printf'\n--- commits from merge base to exact head ---\n'
git log --oneline --decorate "${base}..${head}"printf'\n--- Vitest configuration and package scripts ---\n'
cat -n vitest.config.ts
cat -n package.json | sed -n '1,220p'printf'\n--- active integration implementation ---\n'
cat -n src/lib/covenant/integrations.ts
printf'\n--- integration implementation at merge base ---\n'
git show "${base}:src/lib/covenant/integrations.ts"| cat -n
printf'\n--- all response-cache declarations and authoritative postIntegration calls ---\n'
rg -n -i -C 5 '(Map<.*Record|stringify\(body\)|_stale|last.?known|cache.*response|response.*cache|postIntegration\s*\()' \
src tests --glob '!**/*.md'printf'\n--- native execution route and its route tests ---\n'
sed -n '1,130p' src/app/api/capi/v1/execute/route.ts | cat -n
sed -n '1,260p' src/app/api/capi/v1/execute/route.test.ts | cat -n
printf'\n--- added fail-closed tests ---\n'
cat -n tests/integrations.fail-closed.test.ts
printf'\n--- direct orchestrator execution call sites ---\n'
rg -n -C 5 '\bmcpOrchestrator\.executeTool\s*\(' src --glob '*.ts'

Length of output: 36380


@reprewindai-dev Static review completed for exact head cf3641f7e82332a1f5e5bc0a1fe1b73fb8d04ee0.

No blocking static findings.

Verified:

  • f1b5511 removes Redis response caching and _stale replay from postIntegration().
  • A prior APPROVED result cannot be returned after a timeout, network failure, 5xx response, JSON failure, or invalid payload.
  • HTTP 401 and 403 map to AuthorityDenied.
  • Other integration failures map to IntegrationUnavailable.
  • tests/integrations.fail-closed.test.ts is included by the default Vitest discovery.
  • Native mcp:: execution still calls CAPPO authorization and requires decision === "APPROVED" before mcpOrchestrator.executeTool() runs.

I could not execute tests, lint, build, or security checks in this review environment. GitHub Actions also did not start. Keep the PR unmerged until executable exact-head checks complete. Runtime verification at port 3003 remains separate and required.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/integrations.fail-closed.test.ts`:
- Around line 14-63: Extend the postIntegration fail-closed tests with
rejected-fetch and three-second timeout cases, each following a prior APPROVED
response and asserting IntegrationUnavailable. Use the existing fetch stubbing
and postIntegration patterns, and verify the timeout path exercises the
three-second abort behavior without reusing the earlier successful response.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f4380bba-a4bc-42fd-ba14-ab1f6c069f99

📥 Commits

Reviewing files that changed from the base of the PR and between 63783a0 and cf3641f.

📒 Files selected for processing (2)
  • src/lib/covenant/integrations.ts
  • tests/integrations.fail-closed.test.ts

Comment threadtests/integrations.fail-closed.test.ts
@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Reconciliation update at exact head e04439a15c1310ff96c5a6734ccde60e32e4825a:

  • Added explicit network-rejection and three-second AbortController timeout regressions after a prior APPROVED response.
  • Both paths now assert IntegrationUnavailable; the CodeRabbit coverage thread is resolved.
  • Exact-head cAPI CI run 31666358992 still failed before repository work executed: job 94341648638 has steps: [], runner_id: 0, and no assigned runner.

Source remediation is stronger, but this remains draft/NOT_VERIFIED. Do not merge until exact-head executable test/lint/build/security checks actually run and pass.

@reprewindai-devreprewindai-dev left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head CI is still not executable. Run 31672422971 created verify job 94359673027 with steps=[], runner_id=0 and no runner assignment, then failed before repository code ran. This is CI infrastructure unavailable, not a passing gate. Do not merge or administratively override until an exact-head test/lint/build/security run actually executes and passes. Runtime remains NOT_VERIFIED.

@reprewindai-dev
reprewindai-dev marked this pull request as draft August 13, 2026 08:14
@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Reconciliation against newer main7d01490403117bbbd4c69003f8861606a8a15473: current default branch now routes all consequential /api/capi/v1/execute requests, including mcp:: capabilities, through CAPPO /v1/exec rather than authorizing then executing MCP locally. That is the correct authority boundary and must be preserved when this stale-authority-cache fix lands.

The underlying #44 defect is still present on current main: src/lib/covenant/integrations.ts continues to cache successful POST results in Redis and replay them as _stale after timeout/network/5xx/invalid-response failures. So #44 remains necessary, but it must be rebased/reconciled onto 7d014904... without restoring the removed local MCP execution path.

Keep draft until the branch is reconciled and exact-head executable CI runs and passes. Runtime 3003 remains NOT_VERIFIED.

@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Fresh reconciliation against current cAPI main and new draft #48: keep #44 as the canonical stale-authority-replay remediation, but when it is rebased/refreshed onto current main it must also preserve #48's test-only TypeScript fix (process.env mutable cast confined to registry tests) so the production build remains type-safe. Do not merge #44 or #48 independently around the current Actions outage. Current main remains 7d01490403117bbbd4c69003f8861606a8a15473, where consequential execution is routed through CAPPO; that authority boundary must be preserved while stale POST authority caching is removed. Runtime remains NOT_VERIFIED.

@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Reconciliation against current main is now required before merge. Canonical cAPI advanced to 7d5c5469ae7131a32aec4a5c7d517cfebe664dc0 (fix: protect service registry heartbeats), adding authenticated service-registry heartbeat handling and related registry/MCP hardening. The newer default-branch changes do not overlap this PR's two intended files (src/lib/covenant/integrations.ts, tests/integrations.fail-closed.test.ts), so the correct next step is to rebase/rebuild #44 from 7d5c5469… and reapply only the stale-authority fail-closed patch/tests. Preserve the authenticated registry-heartbeat changes exactly. I attempted the branch ref reset through the connector, but the mutation was blocked by the connector safety layer, so no rebase is being claimed. Keep #44 draft until exact-head test/lint/build/security checks actually execute and pass. Runtime cAPI 3003 remains NOT_VERIFIED.

@reprewindai-dev
reprewindai-devforce-pushed the fix/fail-closed-integration-authority-cache branch from f75eebb to 019ef67CompareAugust 15, 2026 02:19

@reprewindai-devreprewindai-dev left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head reconciliation: the source branch is now correctly rebuilt on current main and preserves authenticated registry heartbeats plus the CAPPO-only execution boundary. However, cAPI CI run 31858895921 failed before repository execution: verify job 94948517014 has steps=[], runner_id=0, and no assigned runner. Keep this PR draft and do not admin-merge. Required gate remains executable exact-head test/lint/build/security checks; this CI result is infrastructure-unavailable, not evidence the code failed.

@reprewindai-devreprewindai-dev left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current cAPI main is now 8d6a692ecae8d239692f9b0bbb091854da6c3372, while this PR is still based on 7d5c5469ae7131a32aec4a5c7d517cfebe664dc0 and GitHub reports it non-mergeable. Fresh current-main inspection confirms the authority defect is still live: postIntegration() continues to cache successful POST authority responses in Redis and replay them with _stale=true after timeout/network/5xx/invalid-response failure. Rebuild/rebase this narrow correction from current 8d6a692e…, preserving the merged MCP incident remediation and docs/MCP_SECURITY_BOUNDARY.md. Reapply only the fail-closed integration-authority change plus focused regressions. Do not merge stale authority across the newer MCP/security lineage. Keep draft until exact-head test/lint/build/security/dependency checks actually execute and pass; reported cAPI port remains 3003 / NOT_VERIFIED until deployed SHA + HTTP/protocol identity + listener + Traefik agree.

@reprewindai-dev
reprewindai-devforce-pushed the fix/fail-closed-integration-authority-cache branch from 019ef67 to 8d6a692CompareAugust 23, 2026 19:21

@reprewindai-devreprewindai-dev left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head merge block after current-main rebuild. This branch is now correctly based on cAPI 8d6a692ecae8d239692f9b0bbb091854da6c3372 and preserves the merged MCP incident/security-boundary work while changing only the fail-closed integration authority path plus focused regressions. However, cAPI CI run 32661008950 concludes failure; job 97247082091 exposes no executable steps. Treat this as CI/gate infrastructure unavailable, not as a passing gate and not as evidence that the tests themselves failed. Keep draft and do not admin-merge until exact-head test/lint/build/security checks actually execute and pass. Reported cAPI port remains 3003 / NOT_VERIFIED until deployed SHA + HTTP/protocol identity + listener + Traefik agree.

@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Exact-head gate clarification for 9e3d34647f67ad433e41d986aa789cdae5c279e6: the latest cAPI CI record is NOT_EXECUTED, not a source-test failure. GitHub recorded runner_id: 0, no runner name, and zero steps on run attempt 7. Therefore no admissible test/lint/build/security evidence exists for this head yet.

Keep #44 draft and do not merge on mergeability alone. Required next evidence is an exact-head hosted/self-hosted runner that actually executes the fail-closed integration tests plus typecheck/build/security checks. Reported cAPI port remains 3003 and verified_runtime_state remains NOT_VERIFIED until deployed SHA + HTTP health/protocol identity + listener + Traefik routing agree.

@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Exact-head rerun diagnosis: the workflow genuinely executed on GitHub-hosted runner and all 21 test files / 70 assertions passed, but Vitest failed the job because the timeout regression created a rejected promise before the rejection assertion was attached (PromiseRejectionHandledWarning / unhandled IntegrationUnavailable). I corrected only the test timing on the existing branch in commit caff3511afbd4f6c80a11415a909b2548dd2c67e: attach the .rejects.toBeInstanceOf(IntegrationUnavailable) expectation before advancing fake timers, then await it after the abort fires. Production integrations.ts is unchanged. Keep this PR draft until a workflow executes against the new exact head and test/build gates pass.

@reprewindai-devChatGPT Codex Connector

Copy link
Copy Markdown
OwnerAuthor

Exact-head reconciliation on caff3511afbd4f6c80a11415a909b2548dd2c67e: cAPI CI run 33222915097 genuinely executed on a hosted runner and passed npm ci, npm test, and npm run build. This clears the prior test/build blocker and confirms the timeout-regression fix is green. Keep this PR draft for now because the repository PR workflow itself currently contains no lint, dependency-audit, secret-scan, or CodeQL/security job, while this PR's stated merge gate explicitly requires lint/security execution. No runtime claim follows from source CI; cAPI remains reported 3003 / NOT_VERIFIED until deployed SHA + health/protocol identity + listener + Traefik agree.

Sign up for freeto 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.

security/governance: fail closed instead of replaying stale cached integration authority

1 participant

@reprewindai-dev