Skip to content

fix: harden Perch for production - #7

Merged
amoreX merged 8 commits into
mainfrom
fix/production-security-hardening
Jul 23, 2026
Merged

fix: harden Perch for production#7
amoreX merged 8 commits into
mainfrom
fix/production-security-hardening

Conversation

@ronishrohan

Copy link
Copy Markdown
Member

Summary

  • Remove hosted shell executionbash_execute and all backend process-creation imports deleted; production runtime uses Node permission model (no --allow-child-process), distroless non-root container image
  • Replace unauthenticated localhost bridgeWebSocketServer/port 7778 removed; replaced by outbound authenticated WSS with Ed25519/P-256 Secure Enclave device keys, HTTPS one-use tickets (header-only), persisted per-device fences
  • Durable run and protocol state — runs, events, acks, action requests, one-use grants, cancellation, and terminal results persist under server-authoritative RLS; in-memory tasks are compatibility-only
  • Tenant isolation — comprehensive USING/WITH CHECK RLS policies, immutable owner constraints, caller-JWT Supabase client for ordinary requests, operation-scoped admin clients; 11 ordered migrations with checksums and advisory locking
  • Disposable VM executor — separate macOS 26 PerchExecutor target with virtualization-only entitlements; pinned Apple Containerization 0.33.3, digest-verified artifacts, typed action registry, open-FD workspace snapshots with symlink/quota enforcement, network entirely denied
  • Signup/OAuth/scheduler hardening — public Supabase email verification, browser-hosted CAPTCHA, distributed fail-closed quotas, immutable pending actions, non-destructive OAuth replacement, replica-safe scheduler leases
  • Runtime observability — split /health/live + /health/ready, correlation IDs, redacted logging, graceful SIGTERM drain, production config validation
  • CI and release gates — pinned actions, dependency-review, TruffleHog; release-macos.yml enforces Developer ID + notarize + spctl + SHA-256 + gh attestation + immutable Vercel Blob; refuses ad-hoc artifacts
  • Site cleanup — private source/issues links removed; download CTA gated on Blob URL; security.txt, SECURITY.md, Dependabot
  • Operator runbooks — database-rollout, device-protocol-rollout, macos-release, security-rollback under docs/runbooks/

Test plan

  • Backend: 120 tests pass, build clean, runtime-policy enforced
  • Site: lint + build clean
  • App: 45 Swift tests pass, build clean
  • Live DB/RLS integration tests gate the migrations-verify CI job
  • Developer ID signing, notarization, Secure Enclave hardware, VM smoke tests: release blockers requiring Apple credentials + macOS 26 Apple silicon

Made with Cursor

Remove hosted shell execution and cross-tenant paths, replace the unauthenticated
localhost bridge with an authenticated outbound device channel, and confine local
execution to an isolated disposable VM. Establish reproducible database, macOS
release, deployment, dependency, and accessibility gates before public launch.

U1 – Contain exploitable legacy paths and baseline CI
- Remove bash_execute and all backend process-execution imports
- Run production service under Node permission model (no child-process grant)
- Distroless non-root Dockerfile, Render freeze config
- Exact versioned default-deny Composio action registry
- Immutable owner-scoped in-memory tasks; allowlisted scheduler PATCH fields
- Non-destructive Composio link migration via pinned connectedAccounts.link
- Production signup/trial/costly-integration freeze with safe existing-user path
- Baseline GitHub Actions CI (backend/site/Swift checks, lockfiles, audits, migrations)

U2 – Reproducible schema and tenant isolation
- Authoritative ordered migrations with checksums, advisory locking, read-only verify
- Safe fingerprint/baseline for existing manually bootstrapped databases
- Comprehensive RLS: immutable ownership, USING+WITH CHECK policies, indexed owners
- Caller-JWT Supabase client for ordinary requests; operation-scoped admin clients
- Generated schema.sql snapshot; migration CI updated to clean bootstrap + verify

U3 – Durable owner/device-scoped run and protocol state
- Persist runs, ordered events, acks, action requests, one-use grants, cancellation
- Versioned typed schemas and exact server-authoritative state reducers
- Interrupted provider streams become explicit recoverable terminal states
- In-memory task cache demoted to compatibility-only delivery state

U9 – Device enrollment and fenced gateway
- Ed25519 / P-256 ECDSA proof-of-possession enrollment with fresh-auth window
- HTTPS-issued short-lived one-use WSS tickets; header-only transport, never URL
- Atomic ticket consumption and persisted fence; identity derived from ticket only
- Strict origin/protocol/payload/rate/backpressure/heartbeat/revocation enforcement
- Express construction moved to app.ts for testability

U10 – Replay, resynchronization, quotas, grants, and recovery
- Durable per-device replay cursors, snapshot resynchronization, quota fail-closed
- Atomic approval → parameter-bound single-use execution grants
- Explicit cancellation, initiating-device affinity, waiting_for_device expiry
- At-least-once transport with idempotent durable outcomes

U4 – macOS identity, storage, and outbound connectivity
- Remove Swifter, WebSocketServer, port 7778
- Data Protection Keychain for sessions; Secure Enclave P-256 device key
- Account-partitioned Application Support (0700 dirs / 0600 files)
- Verified idempotent legacy migration; cross-account data never imported
- Cancellable outbound HTTPS enrollment + authenticated WSS with cursor/replay
- Explicit connection state machine with accessible UI state announcements
- Xcode targets, Hardened Runtime baseline, reviewed non-sandbox entitlements

U5 – VM-backed local executor
- Separate macOS 26 PerchExecutor target with virtualization-only entitlements
- Pinned Apple Containerization (0.33.3) with checksummed artifact manifest
- Exact typed local action registry matching backend grant schema
- One-use grant validation (action hash, params, capabilities, image, device, fence)
- Consent model: names command, mount, write, egress, sensitive output, result upload
- Open-FD workspace snapshots: symlink/hardlink/socket/path-swap/quota enforcement
- Network entirely denied (Containerization cannot destination-filter)
- Authenticated bounded replay-safe app→executor IPC; no host-shell fallback
- Signed persisted idempotent result retry/ack through DeviceConnection

U6 – Signup, OAuth, external actions, and scheduling
- Public Supabase email verification; browser-hosted CAPTCHA; generic responses
- Distributed fail-closed quotas for all costly capabilities
- One-time owner/device/app-bound OAuth with safe non-destructive replacement
- Immutable pending actions with normalized params, device-scoped expiry, terminal reconciliation
- Replica-safe scheduler leases with retry/expiry/cancellation/poison state
- Hosted-vs-bound-device task classification; no server command execution

U7 – Runtime hardening and observability
- Correlation IDs, redacted logging, strict JSON body limits, security headers
- Split /health/live (process-focused) and /health/ready (migration/DB/gateway/provider)
- Graceful SIGTERM drain with configurable DRAIN_DEADLINE_MS
- Production config validation: reject HTTP origins, localhost, insecure fallbacks
- PROVIDER_KEY_SECRET required in production; no silent dev-key fallback

U8 – Signed release, deployment, site, and accessibility gates
- Pinned CI actions; dependency-review; TruffleHog secret scanning
- Separate ci.yml: lint, type-check, protocol schema compat, migration verify, a11y
- release-macos.yml: Developer ID → notarize → staple → spctl verify → SHA-256
  → gh attestation → immutable Vercel Blob upload; refuses ad-hoc artifacts
- Dependabot for npm (backend), npm (site), github-actions, swift ecosystems
- Site: private source/issues links removed; download CTA gated on Blob URL
- security.txt, SECURITY.md, placeholder changelog and security architecture links
- Playwright + axe accessibility tests (WCAG 2.2 AA, keyboard, reduced-motion)
- app/build.sh: Developer ID + notarization path; ad-hoc path warns NOT FOR DISTRIBUTION
- Operator runbooks: database-rollout, device-protocol-rollout, macos-release, security-rollback

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

@ronishrohan must be a member of the MD NIHAL RAHMAN's projects team on Vercel to deploy.
- Click here to add @ronishrohan to the team.
- If you initiated this build, request access.

Learn more about collaboration on Vercel and other options here.

Persist onboarding consent so local monitors only run when enabled, and pin CI to the package's required Swift 6.2 toolchain.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
danotch Ready Ready Preview, Comment Jul 23, 2026 11:49am

Request Review

Restore clean database rollout, make release integrity checks fail closed, and resolve the site's blocking accessibility violations.

Co-authored-by: Cursor <cursoragent@cursor.com>
Require explicit release endpoints, run Swift against the macOS 26 SDK, repair migration syntax, and update vulnerable dependency chains so CI can enforce the launch checks reliably.

Co-authored-by: Cursor <cursoragent@cursor.com>
Parenthesize the CASE expression used by the PL/pgSQL IF condition so PostgreSQL does not parse its first THEN as the end of the IF predicate.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the nonexistent jsonb_object_length call with a supported key-subtraction check so the executor grant migration applies on PostgreSQL 17.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expand the quota constraint to match the seeded 30-day trial window so clean database deployments can complete.

Co-authored-by: Cursor <cursoragent@cursor.com>
Cast polymorphic JSON parameters explicitly and populate the immutable pending-action fields required by the production schema.

Co-authored-by: Cursor <cursoragent@cursor.com>
@amoreX
amoreX merged commit a74fa26 into main Jul 23, 2026
11 of 13 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.

2 participants