> ## Documentation Index
> Fetch the complete documentation index at: https://docs.artifacta.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Concepts

> The mental model behind Artifacta: tenants, artifacts, sessions, and metadata.

## Mental model

```
Tenant
├── API Key(s)
└── Artifacts
    ├── art_abc  ── filename, metadata, session_id, agent_id
    │   └── blob (content-addressed, deduplicated per tenant)
    ├── art_def  ── same session, different agent
    │   └── blob
    └── art_ghi  ── different session
        └── blob (may share storage with art_abc if identical content)

Sessions are optional labels. They can be sealed to prevent late uploads.
Agents are optional labels. No server-side management for either.
```

## Core nouns

<AccordionGroup>
  <Accordion title="Tenant">
    An isolated account. All artifacts, API keys, and usage belong to exactly one tenant. Created automatically when you sign up. Think of it as your project or team.
  </Accordion>

  <Accordion title="Artifact">
    The core object. A single uploaded file with metadata. Has a stable ID (`art_` + 16 alphanumeric chars), a filename, content type, metadata, and belongs to a tenant. Every upload creates a new artifact — no implicit versioning.
  </Accordion>

  <Accordion title="Session">
    An optional, user-defined string grouping artifacts from the same run or workflow. Example: `"pipeline_run_42"`. Not managed by Artifacta — just a label. Sessions can be **sealed** to prevent late uploads.
  </Accordion>

  <Accordion title="Agent ID">
    An optional, user-defined string identifying which agent produced an artifact. Example: `"earnings_analyst"`. Just a label — not managed server-side.
  </Accordion>

  <Accordion title="Metadata">
    A JSON object of key-value pairs attached at upload time. Max 8 KB. Keys must match `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` — **no dots allowed**. Filterable via the API (one key-value exact match per query).
  </Accordion>

  <Accordion title="Content hash">
    SHA-256 hash of file contents. Used for blob-level deduplication within a tenant. Two artifacts with the same content share one blob in storage — invisible to you, saves space.
  </Accordion>

  <Accordion title="TTL">
    Time-to-live. Default: 30 days. Can be overridden per artifact (`--ttl 7d`, `--ttl 90d`, `--ttl never`).
  </Accordion>

  <Accordion title="Download link">
    A temporary, unauthenticated URL (`https://dl.artifacta.io/lnk_xxx`) for sharing artifacts with humans. Default: 7 days. Max: 30 days.
  </Accordion>
</AccordionGroup>

## Key design decisions

<Info>
  **Every upload creates a new artifact.** Uploading `report.pdf` twice produces two distinct artifacts with two IDs. No implicit versioning.
</Info>

<Info>
  **Artifacts are immutable.** Once uploaded, you cannot change content, filename, metadata, or TTL. To correct something, upload a new artifact.
</Info>

<Info>
  **Sessions are labels, not managed objects.** There is no `POST /v1/sessions`. A session exists when at least one artifact references that `session_id`. Sealing is the only explicit session operation.
</Info>

## Artifact lifecycle

```
push → active → expires → garbage collected
              → [delete] → soft-deleted → hard-deleted (30 days)
```

* **Soft delete:** `DELETE` sets `deleted_at`. Artifact disappears from listings and downloads immediately.
* **Hard delete:** Background job removes the Postgres row and R2 blob 30 days after soft delete.
* **Expiration:** Artifacts past their `expires_at` return `410 Gone`. Garbage collected automatically.

## Deduplication

Two separate mechanisms:

| Layer            | Mechanism                                  | What it does                                                                                                                                                                                                                         |
| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Blob storage** | Content-hash (SHA-256) per tenant          | Two artifacts with identical content share one blob in R2. Saves storage. Invisible to you.                                                                                                                                          |
| **API**          | Idempotency key (24h TTL)                  | Same `Idempotency-Key` header within 24h returns the original response. No content comparison. Prevents duplicate artifacts on retry.                                                                                                |
| **CLI**          | Auto-generated `Idempotency-Key` on `push` | The CLI auto-derives a key from `(content + filename + session + agent)` so accidental retries of the same `artifacta push` dedupe by default — no `--idempotency-key` flag needed. Pass `--idempotency-key` explicitly to override. |
