@skydiveai/git-cache 0.1.0-beta.1635 → 0.1.0-beta.2411

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { f as startServer } from "./server-DfaJ_V9K.mjs";
2
+ import { f as startServer } from "./server-DDcKo4yG.mjs";
3
3
  //#region src/cli.ts
4
4
  /**
5
5
  * `git-cache` CLI — the published binary for @skydiveai/git-cache.
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import http from "node:http";
1
2
  import * as _$node_stream0 from "node:stream";
2
3
 
3
4
  //#region src/server.d.ts
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as isProtocolV2Request, c as parseAdvertisement, d as shouldBackfillAfterPassthrough, f as startServer, i as explainRejection, l as parseUpstream, n as classifyUploadRequest, o as metricsSnapshot, r as copyRequestHeaders, s as mirrorHasObjects, t as SidebandPackExtractor, u as recordColdBuildOutcome } from "./server-DfaJ_V9K.mjs";
1
+ import { a as isProtocolV2Request, c as parseAdvertisement, d as shouldBackfillAfterPassthrough, f as startServer, i as explainRejection, l as parseUpstream, n as classifyUploadRequest, o as metricsSnapshot, r as copyRequestHeaders, s as mirrorHasObjects, t as SidebandPackExtractor, u as recordColdBuildOutcome } from "./server-DDcKo4yG.mjs";
2
2
  export { SidebandPackExtractor, classifyUploadRequest, copyRequestHeaders, explainRejection, isProtocolV2Request, metricsSnapshot, mirrorHasObjects, parseAdvertisement, parseUpstream, recordColdBuildOutcome, shouldBackfillAfterPassthrough, startServer };
@@ -298,12 +298,12 @@ function evictAuthCache() {
298
298
  }
299
299
  function validateUpstream(credHeader, upstreamUrl) {
300
300
  return new Promise((resolve) => {
301
- const request = requestUpstream(new URL(`${upstreamUrl}/info/refs?service=git-upload-pack`), {
301
+ const target = new URL(`${upstreamUrl}/info/refs?service=git-upload-pack`);
302
+ const headers = { "user-agent": "git/git-cache-authz" };
303
+ if (credHeader !== null) headers["authorization"] = credHeader;
304
+ const request = requestUpstream(target, {
302
305
  method: "GET",
303
- headers: {
304
- authorization: credHeader,
305
- "user-agent": "git/git-cache-authz"
306
- }
306
+ headers
307
307
  }, (res) => {
308
308
  res.resume();
309
309
  const status = res.statusCode ?? 502;
@@ -341,7 +341,7 @@ function validateUpstream(credHeader, upstreamUrl) {
341
341
  });
342
342
  }
343
343
  async function authorizeCheckThrough(credHeader, repo, upstreamUrl) {
344
- const key = authMemoKey(credHeader, repo);
344
+ const key = authMemoKey(credHeader ?? "", repo);
345
345
  const cached = authCache.get(key);
346
346
  if (cached) {
347
347
  const ttl = cached.allowed ? AUTH_ALLOW_TTL_MS : AUTH_DENY_TTL_MS;
@@ -437,14 +437,12 @@ function parseUpstream(rawPathname, rawSearch = "") {
437
437
  const hadDotGit = Boolean(match[3]);
438
438
  const operation = match[4];
439
439
  let host = authority;
440
- let port = 443;
441
440
  const colon = authority.lastIndexOf(":");
442
441
  if (colon !== -1) {
443
442
  host = authority.slice(0, colon);
444
443
  const p = authority.slice(colon + 1);
445
444
  if (!/^\d{1,5}$/.test(p)) return null;
446
- port = Number(p);
447
- if (port !== 443) return null;
445
+ if (Number(p) !== 443) return null;
448
446
  }
449
447
  host = host.toLowerCase();
450
448
  if (isIpLiteral(host)) return null;
@@ -1681,6 +1679,16 @@ async function proxyInfoRefs(req, res, repo, upstreamUrl, host, credHeader) {
1681
1679
  }, cred);
1682
1680
  });
1683
1681
  }
1682
+ function requestErrorContext(req) {
1683
+ const rawTarget = req.url ?? "";
1684
+ const target = (rawTarget.split("?", 1)[0] ?? "").replace(/^\/[^/?#@]+@/, "/[redacted]@").replace(/^(https?:\/\/)[^/?#@]+@/, "$1[redacted]@");
1685
+ return {
1686
+ method: req.method ?? null,
1687
+ target,
1688
+ targetLength: rawTarget.length,
1689
+ peer: req.socket?.remoteAddress ?? null
1690
+ };
1691
+ }
1684
1692
  async function handle(req, res) {
1685
1693
  const parsed = new URL(req.url, "http://git-cache.local");
1686
1694
  if (parsed.pathname === "/healthz") {
@@ -1737,16 +1745,15 @@ async function handle(req, res) {
1737
1745
  if (config.authMode === "check-through") {
1738
1746
  const header = req.headers["authorization"];
1739
1747
  const raw = Array.isArray(header) ? header[0] : header;
1740
- if (!raw) {
1741
- metrics.auth_denials++;
1742
- res.writeHead(401, {
1743
- "Content-Type": "text/plain",
1744
- "WWW-Authenticate": "Basic realm=\"git-cache\""
1745
- });
1746
- return res.end("authentication required\n");
1747
- }
1748
- const verdict = await authorizeCheckThrough(raw, up.repo, up.upstreamUrl);
1748
+ const verdict = await authorizeCheckThrough(raw ?? null, up.repo, up.upstreamUrl);
1749
1749
  if (!verdict.allowed) {
1750
+ if (!raw && (verdict.status === 401 || verdict.status === 403)) {
1751
+ res.writeHead(401, {
1752
+ "Content-Type": "text/plain",
1753
+ "WWW-Authenticate": "Basic realm=\"git-cache\""
1754
+ });
1755
+ return res.end("authentication required\n");
1756
+ }
1750
1757
  log("info", "auth_denied", {
1751
1758
  repo: up.repo,
1752
1759
  status: verdict.status
@@ -1754,7 +1761,7 @@ async function handle(req, res) {
1754
1761
  res.writeHead(verdict.status, { "Content-Type": "text/plain" });
1755
1762
  return res.end("not authorized for this repository\n");
1756
1763
  }
1757
- clientCred = raw;
1764
+ clientCred = raw ?? null;
1758
1765
  }
1759
1766
  const host = up.repo.split("/")[0] ?? "";
1760
1767
  let uploadBody = null;
@@ -1852,7 +1859,11 @@ async function startServer(options = {}) {
1852
1859
  await cleanupQuarantine();
1853
1860
  const server = http.createServer((req, res) => {
1854
1861
  handle(req, res).catch((error) => {
1855
- log("error", "unhandled", { error: String(error) });
1862
+ log("error", "unhandled", {
1863
+ error: String(error),
1864
+ stack: error instanceof Error ? error.stack : null,
1865
+ ...requestErrorContext(req)
1866
+ });
1856
1867
  if (!res.headersSent) res.writeHead(500);
1857
1868
  res.end();
1858
1869
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skydiveai/git-cache",
3
- "version": "0.1.0-beta.1635",
3
+ "version": "0.1.0-beta.2411",
4
4
  "description": "Sandbox-local Git smart-HTTP clone/fetch cache: a loopback daemon that transparently mirrors HTTPS git reads so repeated clone/fetch/ls-remote skip the origin round-trip. Runs inside an agent sandbox; pushes stay direct.",
5
5
  "homepage": "https://skydive.com",
6
6
  "license": "MIT",
@@ -20,15 +20,6 @@
20
20
  }
21
21
  },
22
22
  "publishConfig": {
23
- "bin": {
24
- "git-cache-daemon": "./dist/cli.mjs"
25
- },
26
- "exports": {
27
- ".": {
28
- "types": "./dist/index.d.mts",
29
- "default": "./dist/index.mjs"
30
- }
31
- },
32
23
  "access": "public",
33
24
  "registry": "https://registry.npmjs.org"
34
25
  },