Skip to content

Block deleted bundle reads from cache#2124

Open
slashdevcorpse wants to merge 6 commits into
Cap-go:mainfrom
slashdevcorpse:codex/capgo-deleted-bundle-read-guard
Open

Block deleted bundle reads from cache#2124
slashdevcorpse wants to merge 6 commits into
Cap-go:mainfrom
slashdevcorpse:codex/capgo-deleted-bundle-read-guard

Conversation

@slashdevcorpse
Copy link
Copy Markdown

@slashdevcorpse slashdevcorpse commented May 11, 2026

Summary

  • Block app-scoped attachment reads when the requested path matches a soft-deleted app_versions.r2_path or a persisted manifest asset path.
  • Run the deleted-bundle check before cache reads and cache-to-R2 restore logic.
  • Keep private download links from resolving deleted bundles.
  • Add indexes for deleted bundle path lookups and persisted manifest path lookups.
  • Add regression coverage for deleted bundle paths, persisted manifest asset paths, and non-deleted cached bundle reads.

/claim #1667

Test plan

  • GitHub CI passed on head 0374e6c.
  • bunx vitest run tests/files-app-read-guard.unit.test.ts
  • bunx vitest run tests/files-app-read-guard.unit.test.ts tests/files-local-read-proxy.unit.test.ts tests/download-link-deleted-bundle.unit.test.ts
  • bunx eslint supabase/functions/_backend/files/files.ts supabase/functions/_backend/private/download_link.ts tests/files-app-read-guard.unit.test.ts tests/files-local-read-proxy.unit.test.ts tests/download-link-deleted-bundle.unit.test.ts
  • git diff --check

Screenshots

Not applicable; backend-only change.

Checklist

  • My code follows the code style of this project and passes the targeted lint checks listed above.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • My change has adequate E2E test coverage.
  • I have tested my code manually, and I have provided steps how to reproduce my tests.

Deleted bundle objects can still have a cached response at the edge. Check the app_versions deletion state for the exact app-scoped r2_path before serving cached attachment bytes, so a soft-deleted bundle cannot be read or restored from cache.

Co-authored-by: Codex <noreply@openai.com>
Copilot AI review requested due to automatic review settings May 11, 2026 01:09
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

Adds a DB-backed soft-deletion guard for app-scoped attachments (checks app_versions/manifest and returns 404), tightens download_link to exclude deleted app_versions, adds indexes, and updates/introduces unit tests plus a shared pgClient mock.

Changes

Soft-Deleted Bundle Read Prevention

Layer / File(s) Summary
Deletion Check Implementation
supabase/functions/_backend/files/files.ts
assertReadableAppScopedAttachment queries public.app_versions (with EXISTS(manifest)) for the requested fileId and throws 404 not_found when a deleted = true match exists.
Download Link Filter
supabase/functions/_backend/private/download_link.ts
app_versions query now requires deleted = false so deleted app versions are excluded from manifest/bundle URL generation.
DB Indexes Migration
supabase/migrations/20260511012637_add_app_versions_deleted_r2_path_index.sql
Adds partial index idx_app_versions_deleted_r2_path on (owner_org, app_id, r2_path) for deleted = true and index idx_manifest_app_version_id_s3_path on manifest(app_version_id, s3_path).
Test Mock Infrastructure
tests/files-app-read-guard.unit.test.ts, tests/files-local-read-proxy.unit.test.ts
Introduces a shared pgClientMock with query = vi.fn() and sets default resolution { rows: [] } in beforeEach.
Files Read Guard Tests
tests/files-app-read-guard.unit.test.ts
New tests assert 404 for soft-deleted .zip and manifest asset paths (verifying queries include FROM public.app_versions or FROM public.manifest and bucketPut is not called), and a case that cached bytes are served for non-deleted bundles.
Download Link Deleted-Bundle Test
tests/download-link-deleted-bundle.unit.test.ts
New test mounts download_link, posts a request, asserts a 400 cannot_get_bundle, verifies deleted = false was applied to the DB filter, and confirms no bundle URL generation occurred.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant assertReadableAppScopedAttachment
  participant PostgreSQL
  participant AttachmentCache
  Client->>assertReadableAppScopedAttachment: GET app-scoped attachment (fileId)
  assertReadableAppScopedAttachment->>PostgreSQL: SELECT FROM public.app_versions / EXISTS(public.manifest) with (owner_org, app_id, fileId)
  alt deleted match found
    PostgreSQL-->>assertReadableAppScopedAttachment: deleted row found
    assertReadableAppScopedAttachment-->>Client: 404 not_found
  else no deleted match
    PostgreSQL-->>assertReadableAppScopedAttachment: no deleted row
    assertReadableAppScopedAttachment->>AttachmentCache: request cached bytes or fallback read
    AttachmentCache-->>Client: 200 + bytes
  end
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly Related PRs

  • Cap-go/capgo#1964: Related changes that add DB checks to files-serving/read guards for deleted app versions and manifests.
  • Cap-go/capgo#2037: Also touches files.ts and app_versions r2_path checks; related guard logic for attachment operations.
  • Cap-go/capgo#2057: Hardens attachment/download-read behavior with DB-level checks similar to this PR.

Poem

🐰 A little rabbit hops and peeks the log,
Guards the bundles by the Postgres bog,
If a version's soft-deleted, it won't run free,
"Not found" it says — safe bytes wait patiently. 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: blocking deleted bundle reads from cache, which is the primary objective across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description includes all required sections: Summary, Test plan with specific command verification steps, Screenshots (marked N/A for backend), and a complete Checklist with most items checked as applicable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 11, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing slashdevcorpse:codex/capgo-deleted-bundle-read-guard (0374e6c) with main (38e5856)2

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (3d184f8) during the generation of this report, so 38e5856 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/files-app-read-guard.unit.test.ts (1)

111-150: ⚡ Quick win

Consider adding a positive test case for non-deleted bundles.

The new test correctly validates that soft-deleted bundles return 404 before serving cached content. However, the test suite lacks coverage for the positive path:

  • App exists ✅ (mocked)
  • Path is valid ✅
  • Bundle is NOT deleted ⚠️ (not tested)
  • Content should be served from cache/R2 ⚠️ (not tested)

This positive case may be covered in integration tests, but adding it here would strengthen confidence that the deletion check doesn't break normal reads.

📝 Suggested test case for non-deleted bundle
it('serves cached content for non-deleted app-scoped bundle paths', async () => {
  getAppByAppIdPgMock.mockResolvedValue({ app_id: 'test-app', owner_org: 'test-org' })
  pgClientMock.query.mockResolvedValue({ rows: [] }) // No deleted bundle found

  const cachedContent = 'valid bundle content'
  globalThis.caches = {
    default: {
      match: async () => new Response(cachedContent, {
        headers: {
          'content-type': 'application/zip',
        },
      }),
      put: async () => { },
    },
  } as any

  const { app: files } = await import('../supabase/functions/_backend/files/files.ts')
  const { createAllCatch, createHono } = await import('../supabase/functions/_backend/utils/hono.ts')
  const { version } = await import('../supabase/functions/_backend/utils/version.ts')

  const appGlobal = createHono('files', version)
  appGlobal.route('/', files)
  createAllCatch(appGlobal, 'files')

  const filePath = 'orgs/test-org/apps/test-app/1.0.0.zip'
  const response = await appGlobal.fetch(
    new Request(`http://localhost/read/attachments/${filePath}`),
    {
      ATTACHMENT_BUCKET: { 
        get: async () => null, // Simulate R2 miss, rely on cache
      },
    },
    { waitUntil: () => { } } as any,
  )

  expect(response.status).toBe(200)
  expect(await response.text()).toBe(cachedContent)
  expect(pgClientMock.query).toHaveBeenCalledWith(
    expect.stringContaining('FROM public.app_versions'),
    ['test-org', 'test-app', filePath],
  )
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/files-app-read-guard.unit.test.ts` around lines 111 - 150, Add a
positive test that mirrors the soft-delete test but mocks pgClientMock.query to
return no rows (bundle not deleted), mocks globalThis.caches.default.match to
return a Response with ZIP content, and provides ATTACHMENT_BUCKET with a get
that returns null (simulate R2 miss) so the cached response is served; in that
test (e.g., it('serves cached content for non-deleted app-scoped bundle
paths'...)) import files, createHono, createAllCatch and version as in the
existing test, call appGlobal.fetch for the same filePath, then assert
response.status === 200, response.text() matches the cached content, and
pgClientMock.query was called with expect.stringContaining('FROM
public.app_versions') and ['test-org', 'test-app', filePath] to mirror the
deletion-check verification.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/files/files.ts`:
- Around line 360-375: The SELECT in the app-scoped attachment read (the
pgClient.query that populates deletedBundlePath in files.ts) is slow because
there is no composite index on public.app_versions for (owner_org, app_id,
r2_path) and no coverage for the deleted flag; add a DB migration that creates
either a full composite index on (owner_org, app_id, r2_path, deleted) or a
partial index like (owner_org, app_id, r2_path) WHERE deleted = true to fully
cover the WHERE clause, then run migrations and remove/adjust any fallback query
changes—locate the query by the deletedBundlePath variable/pgClient.query in
files.ts and create the migration altering public.app_versions accordingly.

---

Nitpick comments:
In `@tests/files-app-read-guard.unit.test.ts`:
- Around line 111-150: Add a positive test that mirrors the soft-delete test but
mocks pgClientMock.query to return no rows (bundle not deleted), mocks
globalThis.caches.default.match to return a Response with ZIP content, and
provides ATTACHMENT_BUCKET with a get that returns null (simulate R2 miss) so
the cached response is served; in that test (e.g., it('serves cached content for
non-deleted app-scoped bundle paths'...)) import files, createHono,
createAllCatch and version as in the existing test, call appGlobal.fetch for the
same filePath, then assert response.status === 200, response.text() matches the
cached content, and pgClientMock.query was called with
expect.stringContaining('FROM public.app_versions') and ['test-org', 'test-app',
filePath] to mirror the deletion-check verification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ecb1ddfe-4732-4476-9ed4-e9a145d19de5

📥 Commits

Reviewing files that changed from the base of the PR and between 3d184f8 and 690befd.

📒 Files selected for processing (2)
  • supabase/functions/_backend/files/files.ts
  • tests/files-app-read-guard.unit.test.ts

Comment thread supabase/functions/_backend/files/files.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR closes a security gap in the files worker where cached bundle bytes could still be served (and potentially restored to R2) after the corresponding bundle path was soft-deleted in public.app_versions.

Changes:

  • Add a Postgres guard that treats app-scoped attachment reads as 404 when the requested path matches a soft-deleted app_versions.r2_path.
  • Ensure this guard runs before any cached attachment content is returned.
  • Add a regression unit test that simulates a cache hit for a deleted bundle path and verifies a 404 is returned.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
supabase/functions/_backend/files/files.ts Adds a DB check in assertReadableAppScopedAttachment to block reads of cached bundle content when the path corresponds to a soft-deleted app_versions.r2_path.
tests/files-app-read-guard.unit.test.ts Updates PG client mocking and adds a regression test ensuring deleted bundle paths return 404 even when cache contains bytes.

Copy link
Copy Markdown

@lyndon050516 lyndon050516 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not merge this without a matching migration for the new app_versions lookup.

I checked the current schema and migrations: app_versions has separate indexes for owner_org, app_id, and deleted, plus deleted = false partial indexes for other paths, but I do not see any index involving r2_path or a deleted = true partial index. Since this guard runs in assertReadableAppScopedAttachment before serving cached content, every app-scoped attachment read now pays for this query before it can use the cache.

A narrow partial index would keep the security guard cheap and scoped to the rows it cares about, for example:

CREATE INDEX IF NOT EXISTS idx_app_versions_deleted_r2_path
  ON public.app_versions (owner_org, app_id, r2_path)
  WHERE deleted = true;

If the migration runner supports concurrent index creation, CONCURRENTLY would also be worth considering. The key point is covering (owner_org, app_id, r2_path) for deleted rows so cache hits do not become repeated table scans as app_versions grows.

slashdevcorpse and others added 4 commits May 10, 2026 21:19
Keep the local read proxy unit test aligned with the app-scoped attachment guard's database lookup by returning an empty app_versions result from the mocked pg client.

Co-authored-by: Codex <noreply@openai.com>
Create a partial app_versions index for deleted R2 paths and cover the non-deleted cached bundle path in the app-scoped read guard tests.

Co-authored-by: Codex <noreply@openai.com>
Extend the deleted bundle guard to manifest asset paths, keep private download links from resolving deleted bundles, and add focused regression coverage for both paths.

Co-authored-by: Codex <noreply@openai.com>
Keep the deleted-bundle download link regression test scoped to local mocks so it does not reset modules during the wider backend suite.

Co-authored-by: Codex <noreply@openai.com>
@slashdevcorpse
Copy link
Copy Markdown
Author

Addressed the index and coverage feedback.

Current head cec23dc now:

  • checks deleted r2_path and stored manifest asset paths before cache reads or cache-to-R2 restore
  • filters deleted bundles in /private/download_link
  • adds the partial deleted-path index plus regression coverage for deleted zip paths, deleted manifest asset paths, non-deleted cached reads, and private download links

CI is green on the current head.

Copy link
Copy Markdown

@SpeedyArt SpeedyArt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the manifest-asset branch of this guard can miss the normal persisted state.

on_version_update copies record.manifest into rows in public.manifest, updates manifest_count, and then clears app_versions.manifest with .update({ manifest: null }). Runtime manifest download paths are also built from public.manifest (download_link.ts -> .from('manifest'), plus the update queries join schema.manifest). So after the trigger has run, the deleted version's asset paths usually live in public.manifest, not in the app_versions.manifest array this query unnests.

That means a cached direct read for a deleted manifest asset can still get rows.length === 0 here and be served from cache, even though the PR now blocks r2_path bundle reads and private download-link lookup. I would change the EXISTS branch to check the persisted table, for example EXISTS (SELECT 1 FROM public.manifest m WHERE m.app_version_id = app_versions.id AND m.s3_path = $3), and add a regression where app_versions.manifest is null but public.manifest contains the deleted asset path. Since this now runs before cache hits, it probably also wants an index covering the manifest lookup such as (app_version_id, s3_path) or (s3_path, app_version_id).

Also adds the manifest lookup index and updates the read-guard regression to cover persisted manifest assets.\n\nCo-authored-by: Codex <noreply@openai.com>
@slashdevcorpse
Copy link
Copy Markdown
Author

Pushed 0374e6c to address the read-guard review feedback.

Changes:

  • The deleted-asset guard now checks persisted public.manifest rows instead of the cleared app_versions.manifest array.
  • Added idx_manifest_app_version_id_s3_path alongside the deleted app_versions.r2_path partial index.
  • Updated the regression to cover persisted manifest asset paths and keep the positive cached-read case.

Validation:

  • bunx vitest run tests/files-app-read-guard.unit.test.ts
  • git diff --check

@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown

@mingisrookie mingisrookie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed current head 0374e6c with focus on the deleted-bundle cache-read guard and the two earlier review concerns. The files worker now checks the primary DB before any cached/R2 response is served, and the guard covers both app_versions.r2_path and persisted public.manifest.s3_path rows for deleted versions. The private /download_link path also filters deleted = false, so it no longer mints bundle/manifest links for soft-deleted rows.

I also checked the performance feedback path: the migration adds the deleted app_versions(owner_org, app_id, r2_path) partial index and the manifest(app_version_id, s3_path) index used by the EXISTS branch.

Local verification passed on the touched scope:

  • bun x eslint supabase/functions/_backend/files/files.ts supabase/functions/_backend/private/download_link.ts tests/download-link-deleted-bundle.unit.test.ts tests/files-app-read-guard.unit.test.ts tests/files-local-read-proxy.unit.test.ts
  • bun x vitest run tests/files-app-read-guard.unit.test.ts tests/files-local-read-proxy.unit.test.ts tests/download-link-deleted-bundle.unit.test.ts → 3 files / 8 tests passed
  • git diff --check 3d184f8..HEAD

No remaining touched-file blocker from me.

@digzrow-coder
Copy link
Copy Markdown

The manifest-file cache guard still has a hole after the normal deleted-version cleanup runs. assertReadableAppScopedAttachment() only blocks a delta object when it can join the requested s3_path back through public.manifest to a deleted app_versions row. But the existing delete path calls deleteManifest() when a version is soft-deleted, and that deletes the manifest rows before/while deleting the R2 objects. If a delta object was already in the edge cache, the later /files/read/attachments/orgs/.../delta/... request no longer has any manifest row to match, so the new query returns empty and the handler can still serve the stale cached object.

The new tests cover the direct bundle r2_path case, but not this manifest-row-removed case. To actually close deleted partial reads, the guard needs a durable tombstone/path index that survives manifest row cleanup, or the delete flow needs to preserve enough path metadata until caches are guaranteed cold. A regression should seed/cache a manifest attachment path, soft-delete the version so its manifest row is removed, then assert the cached /delta/... read is still blocked.

Copy link
Copy Markdown

@KCDaemon KCDaemon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked latest head (0374e6c). The new cache guard still depends on a live public.manifest row to recognize deleted manifest assets:

EXISTS (SELECT 1 FROM public.manifest m WHERE m.app_version_id = public.app_versions.id AND m.s3_path = $3)

But the normal delete flow removes manifest rows during deleteManifest()/version cleanup before or while R2 objects are deleted. Once that row is gone, a cached delta asset request no longer matches the guard, so /files/read/attachments/.../delta/... can still serve stale cached bytes. The added regression only covers the persisted-manifest-row case, not the row-removed-after-soft-delete case.

To close this, persist a durable tombstone/path index that survives manifest cleanup, or preserve enough path metadata until cache/R2 deletion is guaranteed. A regression should seed/cache a manifest asset, run the delete flow so the manifest row is removed, then assert the cached attachment read remains blocked. The PR is currently merge-conflicted (DIRTY); keep blocked until this path is covered.

@austin33133-maker
Copy link
Copy Markdown

The DB-side guard work here looks solid -- the manifest persistence concern @digzrow-coder and @KCDaemon raised is the biggest miss to address before merging. Two additional gaps worth considering since they sit upstream of this guard and aren't covered by the new tests.

1. Edge / CDN caching can serve deleted bundle bytes despite the DB guard

assertReadableAppScopedAttachment runs inside the files worker, which is great for first-fetch paths. But two upstream layers can return a cached copy without invoking the worker:

  • Cloudflare R2 + the worker's own cache.match() paths. If the same fileId was successfully fetched before deletion, Workers Cache (and any CDN sitting in front) may have a 200 response keyed on the URL. assertReadableAppScopedAttachment only protects the slow path. A client hitting the cached path won't run this check at all.
  • Pre-existing browser caches, especially when the underlying R2 object was served with a long Cache-Control: public, max-age=... and no per-org ETag/varying header. The browser revalidates against the URL, not against the DB.

For SaaS billing/customer-data bundles this is the exact "deleted but still accessible" scenario the PR is trying to close. Suggested follow-ups:

  • After app_versions.deleted = true, enqueue caches.default.delete(<canonical url>) for every variant URL that targets the deleted r2_path and persisted manifest.s3_path.
  • Add a Cache-Control: private, must-revalidate (or short max-age) to app-scoped attachment responses so the browser doesn't keep a long-lived copy past deletion.
  • Add a regression test that primes the worker cache for a path, soft-deletes, and asserts the next request returns 404 -- not the cached 200.

2. Signed download links already issued continue to resolve after deletion

download_link.ts now adds .eq('deleted', false) so new signed URLs can't be minted for a deleted bundle. But signed URLs minted before deletion keep working for the remainder of their TTL because the resolver they point to doesn't recheck app_versions.deleted.

If TTLs are short (minutes) the exposure window is small; if TTLs are hour/day-scale (common for big bundle downloads) the deletion is essentially advisory until expiry.

Two options, low to high effort:

  • Cheap: keep the new check, but also wire the soft-delete write to bump a per-app/per-version signing_epoch column and include it in the signed payload, then have the resolver reject if epoch < app_version.signing_epoch.
  • Cheaper still: shorten TTL on download_link issuance and document the window.

A test that issues a signed URL, soft-deletes the version, and asserts the URL returns 404 would make either fix verifiable.


Neither blocks the direct-fetch fix that's the meat of this PR, but both undercut the security claim if left out. Happy to send a follow-up PR with the cache-invalidate path + a regression test if there's interest.

@digzrow-coder
Copy link
Copy Markdown

I could not push to the original slashdevcorpse/capgo PR branch from this GitHub account, so I rebased the fix onto current main and pushed it here:

This addresses the remaining blocker from @KCDaemon: the guard no longer depends only on a live public.manifest row. Before deleteManifest() removes manifest rows, it writes durable deleted_app_version_manifest_paths tombstones keyed by (app_version_id, s3_path), and the attachment read guard checks those tombstones before cache/R2 reads. That keeps cached manifest/delta asset requests blocked after the normal manifest cleanup path has removed the original rows.

Validation on the rebased branch:

  • bun x vitest run tests/files-app-read-guard.unit.test.ts tests/files-local-read-proxy.unit.test.ts tests/download-link-deleted-bundle.unit.test.ts tests/on-version-update-cleanup.unit.test.ts -> 4 files / 13 tests passed
  • bun x eslint supabase/functions/_backend/files/files.ts supabase/functions/_backend/triggers/on_version_update.ts supabase/functions/_backend/private/download_link.ts tests/download-link-deleted-bundle.unit.test.ts tests/files-app-read-guard.unit.test.ts tests/files-local-read-proxy.unit.test.ts tests/on-version-update-cleanup.unit.test.ts
  • git diff --check

I also tried opening a replacement PR from digzrow-coder/capgo to Cap-go/capgo, but GitHub returned digzrow-coder does not have the correct permissions to execute CreatePullRequest. If a maintainer can either allow a PR from that fork or apply/cherry-pick f64ebc3b7, this should remove the stale-cache blocker and the merge conflict at the same time.

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.

8 participants