@@ -0,0 +1,87 @@ |
| 1 | +# Actions caches |
| 2 | + |
| 3 | +Read + delete surface over the `workflow_caches` table — |
| 4 | +shithub's record of cache tarballs uploaded by `actions/cache@v*` |
| 5 | +workflow steps. |
| 6 | + |
| 7 | +The runner-side cache upload protocol that POPULATES the table is |
| 8 | +a separate sprint; this REST surface lands first so operators have |
| 9 | +an audit + purge seat for when caches arrive. |
| 10 | + |
| 11 | +Scopes: |
| 12 | + |
| 13 | +- `repo:read` on list |
| 14 | +- `repo:write` on delete |
| 15 | + |
| 16 | +## Endpoints |
| 17 | + |
| 18 | +``` |
| 19 | +GET /api/v1/repos/{o}/{r}/actions/caches[?key=&ref=&page=&per_page=] |
| 20 | +DELETE /api/v1/repos/{o}/{r}/actions/caches?key=...[&ref=...] |
| 21 | +DELETE /api/v1/repos/{o}/{r}/actions/caches/{cache_id} |
| 22 | +``` |
| 23 | + |
| 24 | +## List response |
| 25 | + |
| 26 | +```json |
| 27 | +{ |
| 28 | + "total_count": 2, |
| 29 | + "actions_caches": [ |
| 30 | + { |
| 31 | + "id": 17, |
| 32 | + "key": "node-modules", |
| 33 | + "version": "8f3b...", |
| 34 | + "ref": "refs/heads/trunk", |
| 35 | + "size_bytes": 1048576, |
| 36 | + "last_accessed_at": "2026-05-12T18:00:00Z", |
| 37 | + "created_at": "2026-05-12T17:00:00Z" |
| 38 | + } |
| 39 | + ] |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +Sorted by `last_accessed_at DESC` so an operator sees the live |
| 44 | +caches first. Standard `Link:` pagination headers are emitted |
| 45 | +when results exceed `per_page` (default 30, max 100). |
| 46 | + |
| 47 | +Filter params: |
| 48 | + |
| 49 | +- `key=<cache_key>` — restrict to a single cache key. |
| 50 | +- `ref=<git_ref>` — restrict to caches created against this ref |
| 51 | + (e.g. `refs/heads/trunk`). |
| 52 | + |
| 53 | +## Delete by id |
| 54 | + |
| 55 | +``` |
| 56 | +DELETE /api/v1/repos/alice/demo/actions/caches/17 |
| 57 | +``` |
| 58 | + |
| 59 | +Returns `204 No Content`. The DB row is removed atomically; the |
| 60 | +tarball in object storage is purged best-effort in the background. |
| 61 | + |
| 62 | +`404` when: |
| 63 | + |
| 64 | +- the cache id is unknown |
| 65 | +- the cache exists but belongs to a different repo (existence-leak-safe) |
| 66 | +- the caller lacks `repo:write` on the target (returned as 404 by |
| 67 | + the policy gate, not 403, to keep the existence-leak guarantee) |
| 68 | + |
| 69 | +## Delete by key |
| 70 | + |
| 71 | +``` |
| 72 | +DELETE /api/v1/repos/alice/demo/actions/caches?key=node-modules |
| 73 | +``` |
| 74 | + |
| 75 | +Removes every cache with that key, regardless of version, scoped |
| 76 | +to the repo. Add `ref=...` to scope by ref as well. Returns `204` |
| 77 | +even when zero rows match (idempotent). |
| 78 | + |
| 79 | +`400` when the `key` query parameter is missing or empty. |
| 80 | + |
| 81 | +## Errors |
| 82 | + |
| 83 | +| Status | Cause | |
| 84 | +|------:|--------------------------------------------------------| |
| 85 | +| 400 | DELETE-by-key without a `key` query parameter. | |
| 86 | +| 403 | PAT lacks `repo:write` on the delete endpoints. | |
| 87 | +| 404 | Cache id unknown or belongs to a different repo. | |