Skip to main content

Registry access log

The audit log records administrative actions. The registry access log records something else: every request a client makes to your organisation’s package and container registry. That covers each download, each metadata read (an npm packument, a PyPI simple index, a Maven maven-metadata.xml), each upload and each delete, and it includes requests that a policy blocked. Nothing is sampled.

What an event holds

FieldMeaning
occurred_atWhen fremforge answered the request (UTC).
originWhich component saw the request: registry for the package registry. The dependency proxy, when it ships, writes proxy.
surfaceapi (/api/packages/…), oci (/v2/…, the container registry) or web (a file downloaded from the web UI).
org, package.type, package.name, package.version, package.fileWhat was asked for.
package.digestsha256:<hex> of the file or manifest that was served or stored, when the registry named it.
actiondownload, metadata, upload, delete or other.
actorWho the registry authenticated: {type: "user" | "bot" | "anonymous", id, login}. A token or a session resolves to the user it belongs to, and Forgejo Actions jobs show as a bot.
client_ipThe client address as fremforge’s edge saw it. It is empty when fremforge could not verify the address, for example on a request that did not come through the edge.
user_agentThe client’s User-Agent, cut at 256 characters.
http.method, http.status, http.bytesThe request method, the answer, and the size where it is known. Size is unknown for a download that is redirected to object storage.
decision, decision_reasonallowed; blocked; would_block (a policy running in shadow mode would have refused it, and the request went through); or pending_refused (your package policy refuses files whose scan has not finished yet, and this file’s had not; the client got 503 with Retry-After, and a retry once the scan finishes succeeds). decision_reason names the rule that decided, for example malware, image_malware, image_cve, registry_scan:<reason> or immutable_retired (see immutable package versions).

Never recorded: an access token, an Authorization header, a cookie or a query string. A presigned storage URL, for example, never appears in an event.

Reading it

With a token that carries audit:read:

curl -sS -H "Authorization: Bearer $FFP_TOKEN" \
  "https://frem.sh/_app/api/v1/orgs/acme/access-log?action=download&type=npm&since=2026-10-01"

Results come newest first. Pass the next value of a page as cursor to get the next page, and stop when next is null. The cursor is a keyset, so events that arrive while you page never shift or repeat a row. Filters: since, until, origin, action, decision, type, name, version, actor (a login, or anonymous) and ip. A page holds up to 500 events. See the API reference for the full shape.

Forwarding it to your SIEM

Access events can be delivered to a SIEM endpoint in the same signed envelope as audit events. The action is registry.access.<action> (for example registry.access.download), and hash_chain is null because access events are not part of the audit hash chain. Delivery is off by default, because download traffic is far larger than audit traffic. Turn it on per endpoint with include_access_log:

curl -sS -X PATCH -H "Authorization: Bearer $FFP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"include_access_log": true}' \
  https://frem.sh/_app/api/v1/orgs/acme/siem/endpoints/$ENDPOINT_ID

An endpoint’s action prefixes apply to access events too. For example, registry.access.upload forwards only uploads.

In the data export

A data export contains access-log.ndjson with every access event fremforge still holds for the organisation, one JSON object per line in the same shape the API returns. The file is covered by the export’s signed manifest.

How long it is kept

Access events follow your organisation’s audit log retention: 90, 180, 365 or 730 days, set at Authentication policy → Audit log retention. The default is 90 days. Older events are deleted once a day. While a legal hold is in place, nothing is deleted.

Who can see the addresses

The access log contains personal data: your users’ logins and IP addresses. The API, the SIEM delivery and the export show both as recorded, because this is your organisation’s own record. fremforge staff tooling sees both only as keyed pseudonyms. Log lines the platform writes for its own operations carry neither.

Limits

  • Git clone and fetch, and reads through the REST API (/api/v1), are not registry requests and are not in this log yet.
  • Deleting a package version through the REST API (DELETE /api/v1/packages/...) or the web UI is not recorded here. The deletes a registry client makes under /api/packages are recorded.
  • A request the platform refused before the registry answered, such as an upload rejected by the malware scanner, has no authenticated actor and shows as anonymous.
  • Delivery from the registry to the log is batched every 2 seconds or every 500 events. If the platform is restarted mid-batch, the events of the last few seconds can be lost. Deliberate drops are logged and alarmed on our side.