Technical guide · security model · v1.2.0
Credential boundaries for secure AI-agent artifact publishing
An AI agent needs permission to deliver work, not a password that unlocks everything a person can read. Artifact Relay separates publishing, private viewing, and selective sharing so each credential crosses a different trust boundary.
Grounded in the Artifact Relay v1.2.0 repository · no claim of protection beyond the documented controls
01 / Design problem
Do not make the agent a viewer.
The publishing process and the human reader have different jobs. Reusing one credential would make a leak or accidental disclosure affect both jobs at once. Artifact Relay instead defines three credential classes, while keeping application data and operator secrets as a fourth operational boundary.
Publisher credential
A bearer token authorizes API publish, source read, provenance-metadata update, and delete calls. Give it only to the trusted publishing process that needs those API operations.
Viewer credential
A viewer password is verified at login and creates a signed browser session. The application stores an Argon2id verifier, not the plaintext password.
Artifact-scoped share credential
An optional share URL grants access to one rendered artifact and its assets. It can expire or be revoked, and does not unlock the private library.
Separation limits credential reuse; it does not make the publisher token narrow. The documented bearer token can publish, update provenance metadata, read original source, and permanently delete artifacts through the API.
02 / Threat model
Threat model and trust boundaries
This model asks what an attacker gains after obtaining one credential or one storage surface. It assumes the host operator, deployment configuration, and Artifact Relay process are trusted. Internet-facing traffic must use the documented HTTPS deployment shape.
| Boundary | Intended holder | What it authorizes | If disclosed | Repository-backed control |
|---|---|---|---|---|
| Publisher credential | Trusted agent runtime or publishing integration | Bearer-authenticated publish, provenance-metadata update, original-source read, and permanent delete API calls | An attacker can act through those API routes until the token is replaced | Generated separately by bootstrap; expected in secret environment, not chat or ordinary config |
| Viewer credential | The human owner | Login to the private library and rendered artifacts; creation and revocation of shares when sharing is enabled | An attacker can browse the private viewer as that user while access remains valid | Plaintext is entered without echo; bootstrap stores only an Argon2id password verifier; login checks are throttled and concurrency-bounded |
| Artifact-scoped share credential | A selected recipient | One rendered artifact and its assets | Anyone holding the URL can use that artifact-level access until expiry or revocation | Sharing is off in local Compose; when enabled it requires an HTTPS base URL and links can expire or be revoked |
Data volume and .env | Host operator | Stored source, assets, SQLite metadata, API token, password verifier, and session signing key across two separate surfaces | Disclosure can expose private content or credentials; loss can prevent recovery or force access reconfiguration | Named volume for data; mode-0600 environment file; data backup excludes .env |
Threats this boundary design addresses
- An agent does not need the viewer password to publish.
- A normal viewer session does not reveal the publisher bearer token.
- A share recipient does not receive library-wide viewer access.
- Disabling sharing makes share-management and
/s/*routes return404, including for links created earlier.
Risks the operator still owns
- Protect the publishing environment: the API token is a bearer credential.
- Protect the host,
.env, persistent volume, and backups from unauthorized access. - Treat share URLs as credentials; recipients can pass them on.
- Use TLS, secure cookies, and restricted proxy trust when the service leaves loopback.
Artifact IDs are opaque paths, but opacity is not viewer authentication. Private artifact pages still require the viewer session, and share URLs must be handled as credentials.
03 / Credential lifecycle
Place each credential where its job runs.
The safest useful placement follows the request path: publisher credential in the agent runtime, viewer credential in the human login flow, and artifact-scoped share credential only with the intended recipient.
- 1
Generate, do not invent
Build the selected release and run
./scripts/bootstrap.sh. It generates the API token and session signing key, asks twice for a viewer password without echo, hashes that password in the application image, and creates.envwith mode0600.Refuses unsafe reuse
The script will not overwrite an existing environment file. Application startup also rejects documented placeholder secrets and incompatible sharing or origin settings.
- 2
Inject the publisher token
Pass the generated bearer token through the secret environment used to launch the trusted agent or integration. Do not copy it into chat, an artifact, source control, or ordinary agent configuration.
Scope accurately
The publisher credential is distinct from viewer access, but it is not write-only: the documented API also permits provenance-metadata updates, original-source reads, and deletes.
- 3
Keep viewing human-facing
Enter the viewer password only into Artifact Relay’s login page. The resulting signed session grants access to the library and private artifact pages.
Share deliberately
When shares are enabled, create one from an authenticated viewer session, choose an expiry where appropriate, and revoke it when its purpose ends.
04 / Local Docker flow
Start with the smallest network boundary.
The base Compose file publishes container port 8000 only on 127.0.0.1, uses local HTTP, and sets SHARE_LINKS_ENABLED=false. That is a workstation flow, not an internet-facing deployment.
git clone https://github.com/eloktev/artifact-relay.git cd artifact-relay git checkout v1.2.0 docker build -t artifact-relay:1.2.0 . ./scripts/bootstrap.sh docker compose up -d docker compose ps curl -fsS http://localhost:8000/api/health
Agent path
Load the token into the publishing process without displaying it. Send it only in the bearer authorization header to the Artifact Relay API. The health endpoint needs no credential and returns no secret data.
Human path
Open the local viewer and authenticate with the viewer password. The publisher does not need that password, and the human does not need to expose the bearer token to browse rendered results.
Moving beyond localhost
Do not expose container port 8000 directly. The repository’s Linux VPS guide terminates TLS with Caddy, keeps the app on loopback, requires COOKIE_SECURE=true, restricts trusted proxy peers, and enables sharing only on an HTTPS origin.
05 / Backup boundary
Back up data and credentials separately.
All persistent application data is in the artifact-data Compose volume. Secrets live in .env and are intentionally excluded from the data archive.
Data backup
./scripts/backup.sh briefly stops the service so SQLite metadata and artifact files share one point in time, creates a mode-0600 artifact-relay-data.tar.gz, and restarts the service if it was running. Store the archive encrypted.
./scripts/backup.sh
Secret backup
Secrets are not in the data archive. Store .env separately in a password manager or secret backup. Without the same signing key, existing sessions are logged out; without the password verifier or API token, access must be reconfigured.
Restore is a controlled replacement, not an extraction shortcut
Back up current data first and restore only into a compatible application version. ./scripts/restore.sh validates archive paths, member types, SQLite integrity, schema compatibility, and recovery state before downtime. It stages the restored tree, retains the previous tree until health succeeds, and keeps recoverable state for operator intervention if safe rollback cannot be confirmed.
./scripts/restore.sh /secure/backups/.../artifact-relay-data.tar.gz curl -fsS http://localhost:8000/api/health
A health response is necessary but not the full acceptance check. The repository runbook also requires logging in and opening a known artifact, while retaining the pre-restore backup until verification completes.
06 / Runbook
Operational checklist
Use this as a review list before connecting an agent or exposing the service beyond one machine.
- ✓Use a pinned release tag or immutable image digest; avoid a moving
latestdeployment. - ✓Generate credentials with bootstrap, retain mode
0600on.env, and never print the file to collect a token. - ✓Put the publisher bearer token only in the trusted agent’s secret environment; keep the viewer password human-facing.
- ✓Keep local Compose on
127.0.0.1. For remote access, follow the documented Caddy HTTPS and proxy-trust configuration. - ✓Leave sharing disabled unless needed. If enabled, use HTTPS, choose expiries, revoke completed shares, and treat URLs as credentials.
- ✓Back up the data volume and
.envseparately; encrypt backup storage and test a compatible restore. - ✓After restore or upgrade, check health, log in, and open a known artifact before discarding the prior backup.
07 / Limits
Non-goals
Credential separation is useful only when its limits are explicit.
Not multi-user authorization
Artifact Relay is documented as a small, single-user gateway. The viewer session is library-wide; this is not a team role or tenant permission system.
Not write-only agent access
The publisher bearer token also authorizes provenance-metadata updates, source reads, and deletes. If an agent needs a write-only capability, that is outside the current API contract.
Not protection from the host operator
The host controls the environment file and persistent volume. This design does not encrypt content against an operator who controls the runtime and storage.
Not a public publishing platform
The default library is private. Selective shares are artifact-scoped credentials, not a promise of anonymous public hosting or discoverability.
Not safe without TLS on the internet
Plain HTTP is accepted only for loopback. Sharing requires an HTTPS base URL, and the VPS path requires secure cookies and restricted proxy trust.
Not a backup policy by itself
Scripts implement consistency and guarded restore mechanics. The operator still chooses encrypted storage, retention, access control, and restore testing.
08 / Verify in source
Read the implementation contract.
This article summarizes repository behavior rather than inventing a parallel security promise. Use the versioned source and runbooks as the operative references.
Apply the model
Publish locally before widening the boundary.
Run one private artifact on loopback, place each credential deliberately, then adopt the documented HTTPS and recovery controls if you move to a server.