Skip to content

feat(connect): classify config access + macOS TCC denial remediation (US2)#707

Merged
Dumbris merged 1 commit into
mainfrom
075-us2-access-classify
Jun 18, 2026
Merged

feat(connect): classify config access + macOS TCC denial remediation (US2)#707
Dumbris merged 1 commit into
mainfrom
075-us2-access-classify

Conversation

@Dumbris

@Dumbris Dumbris commented Jun 17, 2026

Copy link
Copy Markdown
Member

US2 (Spec 075) — access classification + EPERM/TCC remediation surfacing

Implements specs/075-macos-tcc-connect US2 (FR-003/004/005/011, tasks T013–T019), building on US1 (#706).

What changed

  • internal/connect/access.go (new)AccessOutcome, classifyAccess(err) (derives the outcome strictly from the OS error class via errors.Is(err, fs.ErrPermission) / fs.ErrNotExist, never string matching — FR-011), typed *AccessError (Error()+Unwrap, errors.As-friendly), and remediationText building the canonical message with tccutil reset SystemPolicyAppData + prod/dev bundle ids (FR-005).
  • GetStatus — a permission-denied content read now resolves AccessState=denied and populates Remediation, instead of reporting a plain "not connected" (FR-004).
  • Connect/Disconnect — a denial anywhere in the read/backup/write chain returns a typed *AccessError with remediation; unknown-client / already-exists / malformed semantics are preserved.
  • backup.go — failure paths keep wrapping the OS cause with %w so a denial propagates to the Connect/Disconnect classifier (documented).

The four outcomes (accessible/absent/denied/malformed) are now distinct and surfaced; denials are actionable.

Tests (TDD, all -race green)

  • access_test.go: TestClassifyAccess (four-outcome table incl. EPERM/EACCES/wrapped), TestAccessError_ErrorAndUnwrap, TestRemediationText, TestGetStatus_DeniedSurfacesRemediation (T014), TestConnectDenied_ReturnsAccessError (T015).

Verification

  • go build ./cmd/mcpproxy ✅ and go build -tags server ./cmd/mcpproxy
  • go test ./internal/connect/... -race
  • golangci-lint v2.5.0 --config .github/.golangci.yml internal/connect/...0 issues

Scope notes

  • REST field mapping (T025) and docs/troubleshooting note (T028) are Phase-6 Polish, tracked separately. The access_state/remediation JSON fields already exist on ClientStatus (added additively in US1); this PR only populates them — no wire-schema change.
  • Out of scope per spec: Docker probe, entitlements, signing/notarization. US3 (doctor check) is a separate issue.

Related #696

…(US2)

Classify each client-config access into accessible/absent/denied/malformed
strictly from the OS error class (errors.Is on fs.ErrPermission / fs.ErrNotExist),
never from string matching (Spec 075 FR-003/FR-011).

- access.go: AccessOutcome, classifyAccess(err), typed *AccessError
  (Error()+Unwrap, errors.As-friendly) and canonical remediationText with the
  tccutil reset command + prod/dev bundle ids (FR-005).
- GetStatus: a denied content read now resolves AccessState=denied and surfaces
  Remediation instead of a plain "not connected" (FR-004).
- Connect/Disconnect: a permission denial anywhere in the read/backup/write
  chain returns a typed *AccessError with remediation; other error semantics
  (unknown client, already-exists, malformed) are preserved.
- backup.go: failure paths keep wrapping the OS cause with %w so denials reach
  the Connect/Disconnect classifier.

Tests (TDD, -race green): classifyAccess four-outcome table, AccessError
unwrap/As, remediationText contents, GetStatus denied-surfaces-remediation,
Connect denied-returns-AccessError.

Related #696
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: c2a00d8
Status: ✅  Deploy successful!
Preview URL: https://11b52333.mcpproxy-docs.pages.dev
Branch Preview URL: https://075-us2-access-classify.mcpproxy-docs.pages.dev

View logs

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 96.29630% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/connect/access.go 94.59% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

📦 Build Artifacts

Workflow Run: View Run
Branch: 075-us2-access-classify

Available Artifacts

  • archive-darwin-amd64 (28 MB)
  • archive-darwin-arm64 (25 MB)
  • archive-linux-amd64 (16 MB)
  • archive-linux-arm64 (14 MB)
  • archive-windows-amd64 (28 MB)
  • archive-windows-arm64 (25 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (21 MB)
  • installer-dmg-darwin-arm64 (19 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 27714402246 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@mcpproxy-gatekeeper mcpproxy-gatekeeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved: CodexReviewer accept verdict (Paperclip review of record); CI green. Connect US2 access classify + TCC remediation (Spec 075).

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