Artifact Access Model
How Oore CI stores, secures, and serves build artifacts.
Storage backends
Oore CI supports three artifact storage backends:
| Backend | Description | Best for |
|---|---|---|
local | Files stored on the daemon's filesystem | Development, single-machine setups |
s3 | Amazon S3 or S3-compatible storage | Production deployments |
r2 | Cloudflare R2 | Production deployments with Cloudflare |
Configure storage via the Settings API or the web UI. See the Configure Storage guide for step-by-step instructions.
Upload flow
When a runner produces a build artifact:
Runner creates an artifact record via
POST /v1/runners/{runner_id}/jobs/{job_id}/artifacts- Provides: artifact name, type (
apk,ipa,app,generic), file size, and SHA-256 checksum - The daemon validates the artifact name (1-255 characters, no path separators) and checks for duplicate checksums within the build
- Provides: artifact name, type (
Daemon generates an upload URL
- S3/R2: A presigned PUT URL with a 30-minute TTL, targeting
artifacts/{build_id}/{artifact_id}/{name} - Local: A token-based upload path (
/v1/artifacts/local-upload/{token})
- S3/R2: A presigned PUT URL with a 30-minute TTL, targeting
Runner uploads the file to the URL
- Maximum file size: 512 MiB
- The upload URL is single-use and time-limited
Runner finalizes the reservation
POST .../artifacts/{artifact_id}/completemakes the artifact availablePOST .../artifacts/{artifact_id}/abortrecords a failed upload- Pending and failed artifacts are not listed or downloadable
Declared artifact patterns are part of build success: an empty pattern list requires no artifact, while a non-empty list must produce at least one finalized artifact. Missing matches and upload/finalization failures fail the build.
Download flow
When a user wants to download an artifact:
User requests a download link via
POST /v1/artifacts/{artifact_id}/download-link- Requires an authenticated user session with
builds:readpermission - The daemon performs an RBAC check before generating the link
- Requires an authenticated user session with
Daemon generates a signed download URL
- S3/R2: A presigned GET URL with a 15-minute TTL
- Local: A token-based download path (
/v1/artifacts/download/{token})
User downloads the file using the signed URL
- The URL expires after 15 minutes
- Each download-link request generates a fresh URL
Audit logging: The daemon records who requested the download link and when
Signed URL security
Signed URLs are the core security mechanism for artifact access:
| Property | Upload | Download |
|---|---|---|
| TTL | 30 minutes | 15 minutes |
| Auth required to generate | Runner token | User session + builds:read |
| URL reusable | No (single-use for S3) | Until expiry |
| Accessible without session | Yes (presigned) | Yes (presigned) |
The presigned URL model means:
- No credentials in URLs: S3 access keys are never exposed to runners or users
- Time-limited access: URLs expire, preventing stale links from being shared indefinitely
- No proxy bottleneck: Downloads go directly to S3/R2, not through the daemon
Device installation flow
APK and signed ad-hoc IPA artifacts can use the install flow in addition to ordinary downloads:
- An authenticated user with artifact read access requests
POST /v1/artifacts/{artifact_id}/install-link. - Oore creates a reusable, artifact-scoped token that expires after one hour or when the artifact expires.
- Android receives the scoped APK download URL directly.
- iOS receives an
itms-servicesURL whose HTTPS manifest references the scoped IPA download URL.
The iOS token must be reusable because the phone fetches the manifest and IPA separately. The public manifest endpoint validates but does not consume the token. Oore only creates iOS install links for signed ad-hoc artifacts carrying bundle identifier, app name, version, and build number metadata from the current runner.
See Install Mobile Builds for device instructions.
Local backend tokens
For the local storage backend, the daemon manages its own token system:
- A cryptographic token is generated when an upload or download URL is requested
- The token hash is stored in memory with an expiry timestamp
- When the token is used, the daemon validates the hash and checks expiry
- Expired or invalid tokens return
404 Not Found
This provides equivalent security to S3 presigned URLs for local deployments.
Access control layers
Artifact access is protected by multiple layers:
- Runner assignment: Only the runner assigned to a build can create artifacts for that build
- RBAC permissions: Users with artifact read access can download and install; artifact write access is required to administer reusable external share links
- Signed URLs: Time-limited, so sharing a link has a bounded exposure window
- Audit trail: Download link generation is logged for accountability
- Checksum deduplication: Prevents duplicate artifact uploads within a build