@tangle-network/agent-app 0.43.76 → 0.44.1
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/README.md +1 -1
- package/dist/DesignCanvas-Z362I3R3.js +10 -0
- package/dist/{DesignCanvasEditor-FJIVYOA2.js → DesignCanvasEditor-ZFE2W4OJ.js} +4 -4
- package/dist/assets/index.d.ts +4 -4
- package/dist/assets/index.js +223 -11
- package/dist/assets/index.js.map +1 -1
- package/dist/assistant/index.d.ts +7 -7
- package/dist/assistant/index.js +3 -3
- package/dist/assistant/index.js.map +1 -1
- package/dist/{attachment-validation-Dv1A_Puy.d.ts → attachment-validation-DRuLEjAE.d.ts} +1 -1
- package/dist/{auth-_FU8w01b.d.ts → auth-anc7mv2W.d.ts} +2 -2
- package/dist/chat-routes/index.d.ts +14 -11
- package/dist/chat-routes/index.js +16 -17
- package/dist/chat-routes/index.js.map +1 -1
- package/dist/chat-store/index.d.ts +26 -7
- package/dist/chat-store/index.js +14 -5
- package/dist/chat-store/index.js.map +1 -1
- package/dist/{chunk-ROLFDOMJ.js → chunk-4TI7QWLW.js} +3 -3
- package/dist/{chunk-3JUTOVUH.js → chunk-6KMAM7BL.js} +1 -1
- package/dist/chunk-6KMAM7BL.js.map +1 -0
- package/dist/{chunk-WL7XHLDK.js → chunk-ICOHEZK6.js} +77 -5
- package/dist/chunk-ICOHEZK6.js.map +1 -0
- package/dist/{chunk-22GLESKE.js → chunk-O63WWYET.js} +2 -4
- package/dist/chunk-O63WWYET.js.map +1 -0
- package/dist/{chunk-E7N67FYI.js → chunk-Q3FONVAK.js} +5 -5
- package/dist/{chunk-E7N67FYI.js.map → chunk-Q3FONVAK.js.map} +1 -1
- package/dist/{chunk-RXOTWZ4G.js → chunk-TKRI463Z.js} +4 -4
- package/dist/chunk-TKRI463Z.js.map +1 -0
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +123 -4
- package/dist/config/index.js.map +1 -1
- package/dist/{contract-B3h7peV3.d.ts → contract-CEewO6DI.d.ts} +1 -1
- package/dist/design-canvas/index.d.ts +4 -4
- package/dist/design-canvas-react/index.js +7 -7
- package/dist/design-canvas-react/lazy.js +1 -1
- package/dist/eval/index.d.ts +1 -1
- package/dist/eval/index.js +22 -8
- package/dist/eval/index.js.map +1 -1
- package/dist/{flow-types-CqomVAUN.d.ts → flow-types-CJxEmaRy.d.ts} +1 -1
- package/dist/integrations/index.js +67 -5
- package/dist/integrations/index.js.map +1 -1
- package/dist/interactions/index.d.ts +6 -4
- package/dist/interactions/index.js +1 -2
- package/dist/knowledge/index.js +63 -4
- package/dist/knowledge/index.js.map +1 -1
- package/dist/knowledge-loop/index.d.ts +1 -1
- package/dist/knowledge-loop/index.js +94 -4
- package/dist/knowledge-loop/index.js.map +1 -1
- package/dist/{mcp-BjPqQ-3C.d.ts → mcp-D3qVzbE1.d.ts} +2 -2
- package/dist/{mcp-rpc-BfUOsalw.d.ts → mcp-rpc-CzU5LWWT.d.ts} +1 -1
- package/dist/missions/index.js +1143 -23
- package/dist/missions/index.js.map +1 -1
- package/dist/{model-DmdkIteM.d.ts → model-CdCDfBA9.d.ts} +1 -1
- package/dist/object-store/index.js +113 -8
- package/dist/object-store/index.js.map +1 -1
- package/dist/{parts-2ymE5cs-.d.ts → parts-Co_lFgLI.d.ts} +3 -3
- package/dist/platform/index.d.ts +1 -1
- package/dist/preflight/cli.d.ts +13 -0
- package/dist/preflight/cli.js +50 -0
- package/dist/preflight/cli.js.map +1 -0
- package/dist/preset-cloudflare/index.d.ts +1 -1
- package/dist/preset-cloudflare/index.js +284 -11
- package/dist/preset-cloudflare/index.js.map +1 -1
- package/dist/{queue-C24V13h9.d.ts → queue-CD5-_VTX.d.ts} +1 -1
- package/dist/redact/index.js +116 -8
- package/dist/redact/index.js.map +1 -1
- package/dist/runtime/index.d.ts +19 -111
- package/dist/runtime/index.js +234 -14
- package/dist/runtime/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +3 -3
- package/dist/sandbox/index.js +2 -3
- package/dist/sequences/index.d.ts +4 -4
- package/dist/stream/index.d.ts +4 -4
- package/dist/{stream-normalizer-QYUl4vnl.d.ts → stream-normalizer-DnuqkZvw.d.ts} +2 -2
- package/dist/tangle/index.js +42 -4
- package/dist/tangle/index.js.map +1 -1
- package/dist/teams/index.js +5 -5
- package/dist/teams/invitations-api.js +4 -4
- package/dist/teams-react/index.js +3 -3
- package/dist/theme/index.js +0 -1
- package/dist/tools/index.d.ts +6 -6
- package/dist/tools/index.js +5 -7
- package/dist/trace/index.d.ts +1 -1
- package/dist/trace/index.js +179 -10
- package/dist/trace/index.js.map +1 -1
- package/dist/{turn-buffer-BaSgxVmK.d.ts → turn-buffer-BcPfhr1_.d.ts} +1 -1
- package/dist/turn-stream/index.d.ts +1 -1
- package/dist/{types-CBRyqijY.d.ts → types-BCxK0wyS.d.ts} +1 -1
- package/dist/{types-CEchbvgz.d.ts → types-XIZqIdX1.d.ts} +1 -1
- package/dist/web-react/index.d.ts +10 -10
- package/dist/web-react/index.js +5 -5
- package/dist/work-product/index.d.ts +4 -4
- package/dist/work-product/index.js +735 -15
- package/dist/work-product/index.js.map +1 -1
- package/dist/work-product-react/index.d.ts +1 -1
- package/dist/work-product-react/index.js.map +1 -1
- package/package.json +4 -19
- package/dist/DesignCanvas-UNL34LS2.js +0 -12
- package/dist/chunk-22GLESKE.js.map +0 -1
- package/dist/chunk-3JUTOVUH.js.map +0 -1
- package/dist/chunk-5EQCITY3.js +0 -20
- package/dist/chunk-5EQCITY3.js.map +0 -1
- package/dist/chunk-5SD6HT2V.js +0 -236
- package/dist/chunk-5SD6HT2V.js.map +0 -1
- package/dist/chunk-5TESA4SN.js +0 -74
- package/dist/chunk-5TESA4SN.js.map +0 -1
- package/dist/chunk-6GQ5DKFK.js +0 -920
- package/dist/chunk-6GQ5DKFK.js.map +0 -1
- package/dist/chunk-7ESQUSAC.js +0 -343
- package/dist/chunk-7ESQUSAC.js.map +0 -1
- package/dist/chunk-7LNGJDNA.js +0 -1
- package/dist/chunk-7LNGJDNA.js.map +0 -1
- package/dist/chunk-AP2UXKUK.js +0 -69
- package/dist/chunk-AP2UXKUK.js.map +0 -1
- package/dist/chunk-FA4XR66Y.js +0 -32
- package/dist/chunk-FA4XR66Y.js.map +0 -1
- package/dist/chunk-FKCB5FTD.js +0 -126
- package/dist/chunk-FKCB5FTD.js.map +0 -1
- package/dist/chunk-GPBRL2XR.js +0 -102
- package/dist/chunk-GPBRL2XR.js.map +0 -1
- package/dist/chunk-HRH7ASAG.js +0 -759
- package/dist/chunk-HRH7ASAG.js.map +0 -1
- package/dist/chunk-HYTIHYNV.js +0 -297
- package/dist/chunk-HYTIHYNV.js.map +0 -1
- package/dist/chunk-LGBO24FL.js +0 -190
- package/dist/chunk-LGBO24FL.js.map +0 -1
- package/dist/chunk-NLSSFLLS.js +0 -1168
- package/dist/chunk-NLSSFLLS.js.map +0 -1
- package/dist/chunk-OSMNYPOG.js +0 -129
- package/dist/chunk-OSMNYPOG.js.map +0 -1
- package/dist/chunk-QYOD3K56.js +0 -124
- package/dist/chunk-QYOD3K56.js.map +0 -1
- package/dist/chunk-RXOTWZ4G.js.map +0 -1
- package/dist/chunk-UAKFCMWK.js +0 -1
- package/dist/chunk-UAKFCMWK.js.map +0 -1
- package/dist/chunk-UKTYKG57.js +0 -48
- package/dist/chunk-UKTYKG57.js.map +0 -1
- package/dist/chunk-UOAYS72M.js +0 -80
- package/dist/chunk-UOAYS72M.js.map +0 -1
- package/dist/chunk-WL7XHLDK.js.map +0 -1
- package/dist/composer/index.d.ts +0 -2
- package/dist/composer/index.js +0 -22
- package/dist/composer/index.js.map +0 -1
- package/dist/core-7qIM7svy.d.ts +0 -21
- package/dist/durable-chat/index.d.ts +0 -464
- package/dist/durable-chat/index.js +0 -59
- package/dist/durable-chat/index.js.map +0 -1
- package/dist/index.d.ts +0 -51
- package/dist/index.js +0 -827
- package/dist/index.js.map +0 -1
- /package/dist/{DesignCanvas-UNL34LS2.js.map → DesignCanvas-Z362I3R3.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-FJIVYOA2.js.map → DesignCanvasEditor-ZFE2W4OJ.js.map} +0 -0
- /package/dist/{chunk-ROLFDOMJ.js.map → chunk-4TI7QWLW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/object-store/index.ts"],"sourcesContent":["/**\n * `/object-store` — a portable, secure object store for durable large\n * attachments (uploaded PDFs, images, exports) that are too big to ride a chat\n * turn body or live in KV.\n *\n * SECURITY POSTURE (this module guards a legal privilege wall). Every object key\n * carries an operator segment and a customer segment, and access is by a\n * short-lived HMAC-signed URL whose signature covers the EXACT key (operator +\n * customer + upload id + filename) AND the expiry. A tampered key, a swapped\n * customer segment, or a replayed-after-expiry URL all fail the signature or the\n * expiry check and are refused. The signing secret is a PARAMETER on every call\n * — this module reads NOTHING global (no `process.env`, no ambient config); if a\n * product forgets to bind the secret, {@link verifyObjectUrl} fails closed and\n * {@link signObjectUrl} throws rather than minting an unsigned URL.\n *\n * PURE MECHANISM behind two seams: an {@link ObjectStore} port (the R2 impl maps\n * 1:1 to a bucket held behind the structural {@link R2LikeBucket} — so\n * `@cloudflare/workers-types` never leaks into this package's public `.d.ts`)\n * and the signing `secret`. Reads and writes STREAM: {@link createR2ObjectStore}\n * returns the R2 object's `.body` stream directly and never calls\n * `.text()`/`.arrayBuffer()`, so a 15 MB PDF flows through the worker without\n * buffering the whole file into the isolate's heap.\n *\n * RECONCILIATION with the sandbox `storage` seam (`../sandbox` →\n * `SandboxRuntimeConfig.storage`): that is BYOS3/R2 *snapshot* storage — it\n * checkpoints and restores a sandbox box's filesystem for durable session\n * execution. This is a DIFFERENT concern: a content-addressed store for\n * user-facing attachments gated by a signed-URL privilege wall. They are not\n * interchangeable and must not be merged: one persists agent runtime state, the\n * other serves per-operator/per-customer documents to browsers. Do not route\n * artifact downloads through the snapshot bucket, or vice versa.\n */\n\nimport { constantTimeEqual, hmacSha256Base64Url } from '../crypto/web-token'\n\n// ── The store port + R2 impl ────────────────────────────────────────────────\n\n/** Options for a single {@link ObjectStore.put}. Both fields are optional; a\n * store that needs a fixed content length (e.g. R2 with a `ReadableStream`\n * body) uses `contentLength` when present. */\nexport interface PutObjectOptions {\n /** MIME type recorded with the object (returned by `get`/`head`). Advisory:\n * the proxied download route always serves `application/octet-stream`. */\n contentType?: string\n /** Byte length of `body`, when known. Some backends require it for a\n * streamed body; the R2 impl passes a known length through when supplied. */\n contentLength?: number\n}\n\n/** A retrieved object. `stream()` is the ONLY way to read the bytes — there is\n * deliberately no `text()`/`arrayBuffer()`, so a large object never buffers\n * into the isolate heap. */\nexport interface ObjectBody {\n /** The object's bytes as a `ReadableStream` (backed by R2's `.body`). */\n stream(): ReadableStream\n /** Size in bytes. */\n size: number\n /** Recorded MIME type, if any. */\n contentType?: string\n}\n\n/**\n * Portable object-store port. `get`/`head` return `null` on a miss and NEVER\n * throw for a missing key (a miss is a normal control-flow outcome, not an\n * error); `delete` is idempotent.\n */\nexport interface ObjectStore {\n put(key: string, body: ReadableStream | Uint8Array, opts?: PutObjectOptions): Promise<void>\n /** `null` on a miss — never throws for a missing key. */\n get(key: string): Promise<ObjectBody | null>\n /** `null` on a miss — never throws for a missing key. */\n head(key: string): Promise<{ size: number; contentType?: string } | null>\n delete(key: string): Promise<void>\n}\n\n/** Head/metadata shape of a stored object (structural match of R2's `R2Object`). */\nexport interface R2LikeObjectHead {\n size: number\n httpMetadata?: { contentType?: string }\n}\n\n/** Body shape of a retrieved object (structural match of R2's `R2ObjectBody`).\n * `body` is the streamed content — the impl reads this, never `.text()`. */\nexport interface R2LikeObjectBody extends R2LikeObjectHead {\n body: ReadableStream\n}\n\n/**\n * The minimal slice of Cloudflare's `R2Bucket` this module calls. A real\n * `R2Bucket` satisfies it structurally, so the consumer passes its binding\n * without this package ever importing `@cloudflare/workers-types` (which would\n * otherwise leak into the public `.d.ts`).\n */\nexport interface R2LikeBucket {\n put(\n key: string,\n value: ReadableStream | Uint8Array | ArrayBuffer,\n options?: { httpMetadata?: { contentType?: string } },\n ): Promise<unknown>\n get(key: string): Promise<R2LikeObjectBody | null>\n head(key: string): Promise<R2LikeObjectHead | null>\n delete(key: string): Promise<void>\n}\n\n/**\n * Map the {@link ObjectStore} port onto an R2 bucket 1:1. `get` STREAMS: it\n * returns the R2 object's `.body` behind `ObjectBody.stream()` and never calls\n * `.text()`/`.arrayBuffer()`, so a large file flows through the worker rather\n * than buffering into the isolate.\n */\nexport function createR2ObjectStore({ bucket }: { bucket: R2LikeBucket }): ObjectStore {\n return {\n async put(key, body, opts) {\n const options = opts?.contentType ? { httpMetadata: { contentType: opts.contentType } } : undefined\n await bucket.put(key, body, options)\n },\n async get(key) {\n const obj = await bucket.get(key)\n if (!obj) return null\n return {\n stream: () => obj.body,\n size: obj.size,\n contentType: obj.httpMetadata?.contentType,\n }\n },\n async head(key) {\n const obj = await bucket.head(key)\n if (!obj) return null\n return { size: obj.size, contentType: obj.httpMetadata?.contentType }\n },\n async delete(key) {\n await bucket.delete(key)\n },\n }\n}\n\n// ── Key construction + safety ───────────────────────────────────────────────\n\n/**\n * Assert a single object-key path SEGMENT (an operator id, customer id, or\n * upload id) is safe to interpolate into a key, and return it. Throws on the\n * traversal / injection shapes: `..` anywhere, ANY `/` (a segment must be a\n * single path component — a leading, interior, or trailing slash all widen the\n * key by injecting extra levels), a backslash, or an empty segment. Consumers\n * should call this on caller-supplied identifiers BEFORE any `get`/`put` so an\n * attacker-controlled id can never widen the key beyond its own operator+\n * customer prefix.\n */\nexport function assertSafeKeySegment(s: string): string {\n if (s.length === 0) throw new Error('object-store: empty key segment')\n if (s.includes('..')) throw new Error(`object-store: unsafe key segment (contains \"..\") — ${s}`)\n // Reject ANY '/' — leading, interior, or trailing. A key segment is a single\n // path component; an interior slash (`a/b`) would silently add a key level and\n // widen the operator/customer prefix, so it is refused just like a leading one.\n if (s.includes('/')) throw new Error(`object-store: unsafe key segment (contains \"/\") — ${s}`)\n if (s.includes('\\\\')) throw new Error(`object-store: unsafe key segment (backslash) — ${s}`)\n return s\n}\n\n/** Strip a filename down to a safe leaf: drop any path, keep only\n * `[A-Za-z0-9._-]`, and remove leading dots so a `..`/`.hidden`/dot-only name\n * can neither traverse nor vanish. Never returns an empty string. */\nfunction sanitizeFilename(filename: string): string {\n const leaf = filename.split(/[/\\\\]/).pop() ?? ''\n const cleaned = leaf.replace(/[^A-Za-z0-9._-]/g, '_').replace(/^\\.+/, '')\n return cleaned.length > 0 ? cleaned : 'file'\n}\n\n/** Inputs to {@link objectKey}. `customerId` is optional — an unattributed\n * upload lands under the reserved `_unattributed` customer segment. */\nexport interface ObjectKeyParts {\n operatorId: string\n /** Optional — omitted/undefined groups the upload under `_unattributed`. */\n customerId?: string\n uploadId: string\n filename: string\n}\n\n/**\n * Build the canonical object key: `operator/customer/upload-filename`. The\n * operator, customer, and upload segments are asserted safe (throwing on\n * traversal); the filename is sanitized to a safe leaf. The customer segment\n * falls back to `_unattributed` when no customer is attributed. Because a signed\n * URL binds the EXACT key, the operator and customer segments are part of the\n * privilege wall — a caller cannot later swap them without breaking the\n * signature.\n */\nexport function objectKey({ operatorId, customerId, uploadId, filename }: ObjectKeyParts): string {\n const operator = assertSafeKeySegment(operatorId)\n const customer = customerId == null ? '_unattributed' : assertSafeKeySegment(customerId)\n const upload = assertSafeKeySegment(uploadId)\n return `${operator}/${customer}/${upload}-${sanitizeFilename(filename)}`\n}\n\n/**\n * Decode a key ONCE and assert every `/`-delimited segment is safe. Slash- and\n * percent-encoded forms of the same key canonicalize identically (`a/b` and\n * `a%2Fb` both → `a/b`), so a signature binds the key's MEANING, not its\n * on-the-wire spelling. Throws on malformed percent-encoding or an unsafe\n * segment. Our own keys never contain `%`, so the single decode is idempotent.\n */\nfunction canonicalizeObjectKey(raw: string): string {\n let decoded: string\n try {\n decoded = decodeURIComponent(raw)\n } catch {\n throw new Error('object-store: malformed key encoding')\n }\n for (const segment of decoded.split('/')) assertSafeKeySegment(segment)\n return decoded\n}\n\n// ── Signed URLs ─────────────────────────────────────────────────────────────\n\n/** The exact string the signature covers: a versioned JSON of the canonical key\n * and the expiry. JSON escaping makes it delimiter-injection-proof (a key\n * cannot forge the `exp` field). Both sign and verify build it identically. */\nfunction signingMessage(canonicalKey: string, exp: number): string {\n return JSON.stringify({ v: 1, exp, key: canonicalKey })\n}\n\n/** Arguments to {@link signObjectUrl}. */\nexport interface SignObjectUrlArgs {\n /** The exact object key to authorize (from {@link objectKey}). */\n key: string\n /** Absolute expiry in epoch MILLISECONDS (e.g. `Date.now() + 5 * 60_000` for a\n * ~5-minute TTL — the recommended default; keep it short). */\n exp: number\n /** HMAC signing secret. Must be non-empty — signing fails closed otherwise. */\n secret: string\n}\n\n/**\n * Mint a signed query string (`?key=…&exp=…&sig=…`) authorizing a download of\n * `key` until `exp`. The product appends it to its artifact route path\n * (`` `/artifacts${await signObjectUrl(...)}` ``); {@link createProxiedArtifactRoute}\n * / {@link verifyObjectUrl} read it straight off the request URL, so the route's\n * own mount path never matters.\n *\n * FAIL-CLOSED: throws if `secret` is empty (never mints an unsigned URL) and if\n * `key` is unsafe (traversal). Async because the HMAC primitive is WebCrypto.\n *\n * TTL: `exp` is caller-supplied on purpose (the caller knows the sensitivity);\n * keep it SHORT — ~5 minutes is the recommended default for a privilege-walled\n * document.\n */\nexport async function signObjectUrl({ key, exp, secret }: SignObjectUrlArgs): Promise<string> {\n if (!secret) throw new Error('object-store: signObjectUrl requires a non-empty secret (fail-closed)')\n const canonical = canonicalizeObjectKey(key)\n const sig = await hmacSha256Base64Url(signingMessage(canonical, exp), secret)\n const params = new URLSearchParams({ key: canonical, exp: String(exp), sig })\n return `?${params.toString()}`\n}\n\n/** Result of {@link verifyObjectUrl}: the canonical key on success, nothing\n * distinguishing on failure (so a rejection leaks no detail). */\nexport type VerifyObjectUrlResult = { ok: true; key: string } | { ok: false }\n\n/**\n * Verify a signed download request. Reads `key`/`exp`/`sig` off the request URL,\n * canonicalizes the key identically to the signer, recomputes the HMAC and\n * constant-time-compares it, and checks the expiry. Returns the canonical key on\n * success.\n *\n * FAIL-CLOSED everywhere: an empty `secret`, a missing/ malformed parameter, a\n * non-finite expiry, a signature mismatch, or an expired URL all return\n * `{ ok: false }` — and the mismatch path uses a constant-time compare so a\n * near-correct signature is not distinguishable by timing. Async because the\n * HMAC primitive is WebCrypto.\n */\nexport async function verifyObjectUrl(\n request: Request,\n { secret }: { secret: string },\n): Promise<VerifyObjectUrlResult> {\n if (!secret) return { ok: false }\n const url = new URL(request.url)\n const rawKey = url.searchParams.get('key')\n const expRaw = url.searchParams.get('exp')\n const sig = url.searchParams.get('sig')\n if (!rawKey || !expRaw || !sig) return { ok: false }\n\n let key: string\n try {\n key = canonicalizeObjectKey(rawKey)\n } catch {\n return { ok: false }\n }\n\n const exp = Number(expRaw)\n if (!Number.isFinite(exp)) return { ok: false }\n\n const expected = await hmacSha256Base64Url(signingMessage(key, exp), secret)\n if (!constantTimeEqual(expected, sig)) return { ok: false }\n // Signature is valid; enforce expiry last so the constant-time compare always\n // runs (an expired-but-otherwise-valid URL is refused just the same).\n if (Date.now() > exp) return { ok: false }\n return { ok: true, key }\n}\n\n// ── Proxied download route ──────────────────────────────────────────────────\n\n/**\n * Build a download handler that verifies a signed request and STREAMS the object\n * back with a conservative, non-executable content type. Status contract:\n *\n * - `400` — the `key` is missing or malformed (bad encoding / traversal). This\n * is an unauthenticated client error and leaks NOTHING about object existence.\n * - `403` — the signature is missing, wrong, or expired.\n * - `404` — the signature was valid but no object exists at that key (existence\n * is only ever revealed to a validly-signed request).\n * - `200` — streams the bytes with `Content-Disposition: attachment`,\n * `Content-Type: application/octet-stream`, and `X-Content-Type-Options:\n * nosniff`, so the worker never serves active/inline content.\n */\nexport function createProxiedArtifactRoute({\n store,\n secret,\n}: {\n store: ObjectStore\n secret: string\n}): (request: Request) => Promise<Response> {\n return async (request) => {\n // 1. Malformed/missing key → 400, decided BEFORE auth so it leaks no\n // existence signal (a malformed key can never carry a valid signature).\n const rawKey = new URL(request.url).searchParams.get('key')\n if (!rawKey) return new Response('Missing key', { status: 400 })\n try {\n canonicalizeObjectKey(rawKey)\n } catch {\n return new Response('Malformed key', { status: 400 })\n }\n\n // 2. Bad / expired signature → 403.\n const verified = await verifyObjectUrl(request, { secret })\n if (!verified.ok) return new Response('Forbidden', { status: 403 })\n\n // 3. Fetch by the VERIFIED canonical key. Miss → 404 (only reachable behind\n // a valid signature). Hit → stream with a conservative content type.\n const obj = await store.get(verified.key)\n if (!obj) return new Response('Not found', { status: 404 })\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/octet-stream',\n 'Content-Disposition': 'attachment',\n 'X-Content-Type-Options': 'nosniff',\n }\n if (Number.isFinite(obj.size) && obj.size >= 0) headers['Content-Length'] = String(obj.size)\n return new Response(obj.stream(), { status: 200, headers })\n }\n}\n"],"mappings":"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","names":[]}
|