Skip to content
File

Blob: src/worker/cache/policy.ts

typescript46 lines
1import type { CacheContext } from "./cache";
2 
3// Cache-policy discriminator used by visibility-aware request paths to
4// decide whether the shared Workers Cache may be read or written. Public
5// repositories cache freely; private repositories must bypass shared
6// cache reads/writes regardless of upstream success.
7export type SharedCachePolicy = "allow-shared-cache" | "bypass-shared-cache";
8 
9// CacheContext memo flag tags. `no-cache-read`/`no-cache-write` are honored
10// by the shared cache helpers; route handlers that mark a request private
11// must set both before calling any cache-aware loader.
12const NO_CACHE_READ = "no-cache-read";
13const NO_CACHE_WRITE = "no-cache-write";
14 
15// Marks a request as private so any downstream shared-cache lookup or
16// write is skipped. Idempotent: callers can mark private once at gate
17// time and trust that all subsequent helpers honor it.
18export function markRequestPrivate(cacheCtx: CacheContext): void {
19 cacheCtx.memo = cacheCtx.memo || {};
20 cacheCtx.memo.flags = cacheCtx.memo.flags || new Set<string>();
21 cacheCtx.memo.flags.add(NO_CACHE_READ);
22 cacheCtx.memo.flags.add(NO_CACHE_WRITE);
23}
24 
25// Returns true if the request was marked private (private repo, sensitive
26// data path, etc.). Used to gate shared-cache reads/writes and to pick the
27// `Cache-Control` response header.
28export function isRequestPrivate(cacheCtx: CacheContext | undefined): boolean {
29 return cacheCtx?.memo?.flags?.has(NO_CACHE_READ) === true;
30}
31 
32// HTTP `Cache-Control` value for responses serving repo data over Git or
33// data APIs:
34// - `mutating: true` -> always "no-store" (credentialed mutating paths
35// such as receive-pack must never sit in shared caches).
36// - private (membership-derived) request -> "no-store".
37// - otherwise -> "no-cache" so downstream caches re-validate but may
38// reuse bodies briefly.
39export function responseCacheControl(
40 cacheCtx: CacheContext | undefined,
41 options?: { mutating?: boolean }
42): "no-store" | "no-cache" {
43 if (options?.mutating) return "no-store";
44 return isRequestPrivate(cacheCtx) ? "no-store" : "no-cache";
45}