Skip to content

Extract transport-agnostic proxy core as varlock/proxy-core - #964

Open
theoephraim wants to merge 2 commits into
mainfrom
proxy-core-extraction
Open

Extract transport-agnostic proxy core as varlock/proxy-core#964
theoephraim wants to merge 2 commits into
mainfrom
proxy-core-extraction

Conversation

@theoephraim

@theoephraim theoephraim commented Jul 31, 2026

Copy link
Copy Markdown
Member

What

Extracts the credential proxy's transport-independent logic out of runtime-proxy.ts (1580 lines, interleaved with node http/tls) into src/proxy/core/, shipped as a new public subpath export: varlock/proxy-core.

What moved (verbatim where possible):

  • types.ts and policy.ts (already pure) plus policy.test.ts
  • substitution.ts: substitution guards, placeholder<->real replacement, uninjected-placeholder detection
  • scrub.ts: leak detection, scrubbed-key detection, and a new StreamingScrubber that owns the chunk-carry/hold-back logic for streamed responses (node wraps it in a Transform; a fetch-based gateway can wrap it in a Web TransformStream)
  • headers.ts: header transforms and response-redaction predicates, re-typed against a neutral HeadersRecord
  • auth.ts: Proxy-Authorization parsing and the data-plane gate, with portable (Buffer/node:crypto-free) base64 and constant-time compare
  • activity.ts: the ProxyActivity/ProxyAuditDecision types (audit.ts re-exports them)
  • pipeline.ts: the shared request decision order as a two-phase pure pipeline (pre-body: egress gate -> policy -> item scoping -> cleartext guard; with-body: uninjected-placeholder guard -> substitution guards -> approval gate -> substitution), returning blocked/forward outcomes with the exact same messages, audit activities, and teardown behavior as before

runtime-proxy.ts is now the node adapter: listeners, CONNECT/MITM, CA handling, verified-upstream-identity forwarding, and response streaming, driving the shared pipeline. The two-phase split preserves the existing behavior of not buffering request bodies for requests denied pre-body.

Packaging

The first iteration made this a private workspace package bundled via noExternal, but that leaked unresolvable @varlock/proxy-core imports into the published declarations (review finding). tsup's dts resolve cannot inline source-only workspace packages (verified; the published package has the same long-standing issue with @env-spec/utils/type-utils), so instead of publishing another package the core lives inside varlock and ships as the varlock/proxy-core subpath. Future gateway adapter packages (@varlock/cloudflare-gateway etc.) import it from there with working types.

The subpath is built by a second sequential tsup invocation (tsup.proxy-core.config.ts) with platform: 'neutral', which doubles as build-time enforcement that no node builtin sneaks into the core. It is a separate invocation because tsup builds array configs in parallel and the main dts pass deletes the other config's d.ts output.

Why

First slice of running the proxy on fetch-shaped gateway hosts (Cloudflare Workers first, Vercel later): those adapters need the policy/substitution/scrub pipeline without node transport types. Also makes the security-critical decision order independently testable.

No behavior change intended; the full proxy suite (including the TLS/MITM integration tests and the Bun Invariant #1 check) passes unchanged, and dist now contains no imports of private workspace packages from the proxy core.

The credential proxy's policy evaluation, substitution guards, placeholder
substitution, response scrubbing, auth-token parsing, and the shared request
pipeline (egress gate -> policy -> cleartext guard -> uninjected-placeholder
guard -> substitution guards -> approval gate -> substitute) now live in a
private workspace package with no node transport dependencies, bundled into
varlock via tsup noExternal. runtime-proxy.ts becomes the node adapter:
servers, MITM, CA handling, upstream identity verification, and streaming
stay put, built on the shared core.

This is the first slice of hosting the proxy on fetch-shaped gateways
(Cloudflare Workers, Vercel), which will reuse the same core.
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

bumpy-frog

The changes in this PR will be included in the next version bump.

minor Minor releases

  • varlock 1.15.0 → 1.16.0

Bump files in this PR

Click here if you want to add another bump file to this PR


This comment is maintained by bumpy.

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle size

⚠️ grows the bundle by 148.1 KB (+3.0%)

Metric main This PR Δ
Total dist 4922.2 KB 5070.2 KB +148.1 KB (+3.0%)
JS 1692.0 KB 1721.3 KB +29.3 KB (+1.7%)
Sourcemaps 3154.2 KB 3246.8 KB +92.7 KB (+2.9%)
Type defs 76.0 KB 102.1 KB +26.1 KB (+34.3%)

dist/ only; native binaries are versioned separately and not counted here.

@pullfrog pullfrog Bot 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.

Important

The published TypeScript declarations retain an unavailable private-package import, so this needs one packaging fix before merge.

Reviewed changes in 160160a8: the complete extraction of the proxy's transport-neutral behavior and its Node adapter integration.

  • Core package: Moves policy, proxy types, substitution guards, authentication, response-header handling, and activity types into private workspace package @varlock/proxy-core.
  • Request pipeline: Introduces pre-body and body-dependent phases while retaining the egress, policy, cleartext, approval, substitution, audit, and tunnel-teardown sequence.
  • Streaming response handling: Encapsulates cross-chunk secret scrubbing in StreamingScrubber while the Node adapter retains byte decoding and response transport behavior.
  • Build integration: Bundles the private package into varlock JavaScript and redirects existing source and test imports to its subpath exports.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using azure/gpt-5.6-sol𝕏

Comment thread packages/varlock/package.json Outdated
@pkg-pr-new

pkg-pr-new Bot commented Jul 31, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/varlock@964

commit: e0ffc78

Per review: the private-package approach leaked unresolvable
@varlock/proxy-core imports into the published d.ts files (tsup's dts
resolve cannot inline source-only workspace packages; the same
pre-existing issue exists for @env-spec/utils/type-utils). Instead of
publishing another package, the core now lives at src/proxy/core inside
varlock and ships as a public subpath export, varlock/proxy-core, so
gateway adapter packages can import it with working types.

The subpath is built by a second sequential tsup invocation with
platform 'neutral', which doubles as build-time enforcement that no
node builtin sneaks into the core. (A second entry in the main config
array does not work: tsup builds array configs in parallel and the main
dts pass deletes the other config's d.ts output.)
@theoephraim theoephraim changed the title Extract transport-agnostic proxy core into @varlock/proxy-core Extract transport-agnostic proxy core as varlock/proxy-core Jul 31, 2026

@pullfrog pullfrog Bot 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.

ℹ️ No critical issues; one stale package reference remains inline.

Reviewed changes since the prior Pullfrog review, focusing on the replacement of the private workspace package with a published Varlock subpath.

  • Published core: Moved the extracted source under packages/varlock/src/proxy/core and exposed it as varlock/proxy-core.
  • Neutral build: Added a sequential neutral-platform tsup pass that emits self-contained JavaScript and declarations for the new subpath.
  • Declaration fix: Removed all private @varlock/proxy-core dependencies and restored resolvable generated declarations for Varlock consumers.
  • Release metadata: Updated the package bump and changeset to describe the new public API.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using azure/gpt-5.6-sol𝕏

// Shared request pipeline for both transports (MITM tunnel + absolute-form http).
// The decision order — egress gate → per-call policy (block) → cleartext guard →
// uninjected-placeholder guard → substitution guards → approval gate →
// scrub+inject — lives in @varlock/proxy-core's two-phase pipeline; this

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.

@varlock/proxy-core no longer exists after this commit, so this comment and the matching comment in audit.ts:9 point maintainers to the removed package. Please rename both references to varlock/proxy-core, or describe the shared core without a package name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant