# BagIt Integrity Report (`l3digital/bagit-integrity-report`) Actor

Experimental full-payload integrity reports for one bounded public BagIt ZIP.

- **URL**: https://apify.com/l3digital/bagit-integrity-report.md
- **Developed by:** [L3Digital](https://apify.com/l3digital) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.05 / complete integrity report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## BagIt Integrity Report

Get one structured integrity report for a bounded BagIt ZIP without installing a
validator in your calling application. This experimental Actor checks the complete
supported payload inventory and every available listed payload/tag target against
its checksums. It reports missing, unexpected and changed files with coverage and
acquisition provenance.

### Use from an AI agent through MCP

Add this URL to a client that supports remote HTTP MCP, then authorize with your
own Apify account using the [Apify MCP setup guide](https://docs.apify.com/integrations/mcp):

```text
https://mcp.apify.com/?tools=l3digital/bagit-integrity-report
```

This configuration selects the Actor directly. Availability still depends on
Apify account and Actor eligibility. Call `l3digital/bagit-integrity-report`
with the example input below; the pricing and input restrictions on this page apply.

When using `call-actor`, its response contains run status and storage IDs. If the
run is still active, check that run with `get-actor-run`. After success, retrieve
the report with `get-dataset-items` using the returned dataset ID
(`defaultDatasetId` in the run API). These retrieval tools load with the Actor.
Retrieve the existing result instead of starting another run. Inspect the report
status and the coverage or refusal fields described below before using its values.

### Try the example

The default input runs a tiny built-in public-domain synthetic bag through the
same complete validator:

```json
{"mode": "demo"}
```

The example performs no network request, returns `example: true` and
`useful: false`, and never charges a report event. It demonstrates correctness;
it is not external demand or a repository acceptance decision.

For an authorized public ZIP, use:

```json
{"mode": "url", "url": "https://example.org/your-bag.zip"}
```

Replace the placeholder with your own authorized public package URL. Only HTTPS
is accepted. Queries, fragments, userinfo, explicit ports and non-public DNS
answers are refused. Redirects receive the same checks. No source credentials,
cookies, proxy configuration or caller headers are forwarded.

The Console form lists both fields. The Actor validates their relationship at
runtime: `url` is required in URL mode and must be omitted entirely in demo mode,
including any explicit `null` value. Invalid input fails before acquisition or
report charging. The platform form schema does not express these conditional rules.

### Supported packages

- BagIt 1.0 with UTF-8 tag files, packaged at ZIP root or under one enclosing directory.
- Stored or deflated ZIP entries, at least one SHA-256 or SHA-512 payload manifest,
  and a `data/` directory. Both allowed algorithms and corresponding tag manifests
  are checked when present.
- Optional bag-info and ordinary tag files within the fixed limits.

Other versions, encodings, algorithms, `fetch.txt`, encrypted archives and special
entries are unsupported. The Actor never downloads missing payload files.
Percent/CR/LF filenames or target tokens, surrounding whitespace and leading-star
target forms are unsupported because the pinned parser can alter their identity.
Ordinary internal spaces and exact Unicode remain supported.
Unsafe paths, duplicates, file/directory collisions and ambiguous Unicode names
are refused. Exact nonambiguous Unicode names are retained. The scope does not
include repair, profiles, certification or repository acceptance.

### Results and charging

One dataset item contains `schemaVersion`, `supportedScope`, `status`,
`validationComplete`, `example`, `useful`, `reasonCode`, `findings`,
`findingsOmitted`, `coverage`, `limits` and `provenance`.

| Status | Meaning | Useful paid event |
| --- | --- | --- |
| `valid` | Complete supported validation found no integrity fault. | Productive runs only. |
| `invalid` | Diagnosed supported integrity faults, or malformed required structure. | Only complete productive validation. |
| `unsupported` | Scope, safety or resource limits prevent the promised evaluation. | No. |
| `fetch_error` | Secure acquisition failed or was refused. | No. |

Missing/extra payload and checksum mismatches can coexist. Complete invalid reports
retain all diagnosed faults; missing bytes are explicitly absent rather than
reported as hashed. Findings sort by code and relative path. More than 100
findings are capped only after complete computation, with the exact omitted count.

For pay-per-event runs, the configured `report-produced` capacity is checked before
productive acquisition. One event is charged only after a useful report is
persisted. Persistence failure never charges. A rejected charge fails the run
honestly after persistence; it is not retried. Separate invocations are separate
requests. The initial experimental price is $0.05 per persisted complete
productive `valid` or `invalid` report. Demo runs, refusals, fetch failures and
incomplete validation do not charge a report event.

Private hosted QA produced the intended valid, checksum-mismatch and unsupported
reports. Those owner tests do not establish customer demand or paid settlement.
Full-limit latency/cost and commercial margin remain unmeasured. For large or
private packages, use a local BagIt validator; this experimental service tests
the convenience of a bounded hosted call.

### Fixed limits

Compressed ZIP: 32 MiB (33,554,432 bytes). Expanded content: 64 MiB
(67,108,864 bytes). ZIP entries including directories: 1,000. Paths: 1,024
characters. Parsed bagit.txt/bag-info/manifest/tagmanifest content: 8 MiB
(8,388,608 bytes) cumulatively; ordinary unparsed tag files do not consume this
additional ceiling. Distinct declared targets across algorithms: 1,000. Acquisition: 20 seconds. Aggregate acquisition/materialization/
validation: 120 seconds. At most five redirects and six requests; no retries.
Limits are inclusive and cannot be raised through input.

### Privacy and provenance

Process only packages you are authorized to inspect. Raw ZIP/payload bytes exist
in temporary state and are removed after success, refusal, error or timeout.
Reports contain source hostnames, ZIP SHA-256/byte count, request/redirect counts,
validator version and authorized bag-relative filenames. They omit full URLs,
source paths/queries, IP addresses, payload contents and raw exceptions.
Apify retains the input URL and dataset according to its normal platform/caller
retention settings; the Actor does not promise deletion of platform-managed input.

### Development

Python 3.13, pinned Apify SDK, Pydantic v2 and bagit1.9.0 are locked with uv.

```bash
uv sync --locked --all-groups --python 3.13
uv run --locked ruff format --check .
uv run --locked ruff check .
uv run --locked pyright
uv run --locked pytest
uv run --locked pip-audit
```

Repository agents execute these workloads through `rexec`. Tests use synthetic
fixtures and fake SDK/network boundaries, never public downloads or paid runs.
See [VALIDATION.md](VALIDATION.md) for observed evidence and remaining hosted
unknowns. [PRODUCT.md](PRODUCT.md) records the experimental product scope.

# Actor input Schema

## `mode` (type: `string`):

Demo mode forbids URL input. URL mode requires one public HTTPS ZIP URL.

## `url` (type: `string`):

Required in URL mode; omit entirely in demo mode. Authorized public HTTPS ZIP. No query, fragment, userinfo, explicit port or private destination. The Actor enforces these rules at runtime.

## Actor input object example

```json
{
  "mode": "demo"
}
```

# Actor output Schema

## `results` (type: `string`):

The default dataset contains one report for the requested BagIt ZIP.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "demo"
};

// Run the Actor and wait for it to finish
const run = await client.actor("l3digital/bagit-integrity-report").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "mode": "demo" }

# Run the Actor and wait for it to finish
run = client.actor("l3digital/bagit-integrity-report").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "demo"
}' |
apify call l3digital/bagit-integrity-report --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,l3digital/bagit-integrity-report"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/8lSvc2OOJ5KSd5z5H/builds/phhYsiGr54CPhXc8s/openapi.json
