Metadata-Version: 2.4
Name: fetchseal
Version: 0.1.0a3
Summary: Compile an untrusted public URL into a bounded, verifiable context artifact
Project-URL: Repository, https://github.com/ShiroKSH/fetchseal
Project-URL: Documentation, https://github.com/ShiroKSH/fetchseal/tree/main/docs
Project-URL: Issues, https://github.com/ShiroKSH/fetchseal/issues
Project-URL: Security, https://github.com/ShiroKSH/fetchseal/security/policy
Author-email: ShiroKSH <kushidashiro@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: citations,context,provenance,security,ssrf
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: hypothesis>=6.100; extra == 'dev'
Requires-Dist: jsonschema>=4.23; extra == 'dev'
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pip-audit>=2.7; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest-cov>=6; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.9; extra == 'dev'
Requires-Dist: twine>=6; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.8; extra == 'mcp'
Description-Content-Type: text/markdown

# FetchSeal

Fetch public HTTP(S) resources under a strict network policy and turn them into
verifiable, citation-ready artifacts. Remote content remains untrusted data.

> **Alpha:** FetchSeal is pre-release software published on PyPI. Expect API
> changes before 1.0.

## Install

FetchSeal requires Python 3.11 or newer; CI tests Python 3.11–3.14. Install the
base package from PyPI:

```console
python -m pip install fetchseal
```

For the `v0.1.0a3` GitHub prerelease, download and verify the attested wheel
before installing it:

```console
gh release download v0.1.0a3 --repo ShiroKSH/fetchseal --pattern "*.whl"
gh attestation verify fetchseal-0.1.0a3-py3-none-any.whl --repo ShiroKSH/fetchseal
python -m pip install fetchseal-0.1.0a3-py3-none-any.whl
```

The project has no core runtime dependencies. The optional MCP adapter is
separate. It applies stricter extraction limits and rejects serialized artifact
payloads larger than 4 MiB:

```console
python -m pip install "fetchseal[mcp]"
```

## CLI

```console
fetchseal https://example.com --format json
fetchseal inspect https://example.com --format json
fetchseal https://example.com --record --cache-dir .fetchseal
fetchseal replay sha256:CAPTURE_ID --cache-dir .fetchseal
fetchseal diff artifact-before.json artifact-after.json --format json
fetchseal schema --format json
```

`--metadata-only` still downloads, bounds, decodes, and hashes the response
body; it skips only document extraction. It is not a `HEAD` request.

Strict defaults accept only GET/HEAD over HTTP or HTTPS to globally routable
addresses on ports 80/443. FetchSeal does not read proxy variables, `.netrc`,
browser cookies, or ambient authorization.

## Python

```python
from fetchseal import fetch

artifact = fetch("https://example.com")
print(artifact.content.text)
print(artifact.provenance.body_sha256)
print(artifact.sections[0].citation_id)
artifact.verify()
```

Sync and async clients share the same policy and transport logic:

```python
from fetchseal import AsyncClient, Client, StrictPolicy

with Client(policy=StrictPolicy()) as client:
    artifact = client.fetch("https://example.com")

async with AsyncClient(policy=StrictPolicy()) as client:
    artifact = await client.fetch("https://example.com")
```

## Artifact shape

Artifacts use versioned ContextArtifact v1 JSON. This deliberately abridged
example is not a complete schema-valid artifact:

```json
{
  "schema_version": "1.0",
  "content_id": "sha256:<decoded-body-hash>",
  "capture_id": "sha256:<stable-capture-fingerprint>",
  "trust": {
    "classification": "untrusted_external_content",
    "instructions_are_data": true,
    "active_content_executed": false
  },
  "content": {
    "text": "Example Domain",
    "sections": [{"citation_id": "S0001-..."}],
    "links": []
  }
}
```

`capture_id` excludes only fetch timestamps, elapsed time, and itself. This is
an intentional stable-fingerprint contract: `capture_id` does not authenticate
those volatile fields or prove freshness. Canonical JSON uses UTF-8, sorted
keys, no insignificant whitespace, and no non-finite numbers. `verify()` checks
the full nonvolatile artifact fingerprint, body and content-ID hash consistency,
text and section hashes, citation IDs, trust constants, and schema version. The
fingerprint detects inconsistency; it is not an origin-authentication signature.

## Security guarantees

Within the documented threat model, strict mode provides:

- strict absolute URL parsing, valid Unicode scalar values, a post-encoding
  8,192-character ceiling, and lossless IDNA normalization: Unicode hosts are
  NFC-normalized, lowercased, and rejected if encode/decode changes them;
- denial of userinfo, ambiguous numeric hosts, local names, special IP ranges,
  cloud metadata and platform-service addresses including Azure WireServer
  (also through IPv4-mapped IPv6 and NAT64), and non-default ports;
- fail-closed evaluation of every DNS answer;
- a TCP connection to the selected IP, with the original host retained for HTTP
  Host, TLS SNI, and certificate hostname verification;
- actual socket peer comparison with the selected IP before request bytes;
- full revalidation and a fresh connection for every manual redirect;
- no TLS downgrade, proxy, credentials, cookies, HTTP/2 coalescing, JavaScript,
  subresource loads, external XML entities, or telemetry;
- explicit limits on resolver concurrency, time, informational responses, HTTP
  chunks, headers, raw/decoded bytes, decompression ratio, JSON nodes, document
  structure, text, Markdown, whitespace normalization, heading paths, link URLs,
  locators, sections, and links; oversized HTML links are rejected before URL
  joining;
- pre-parse JSON root/cardinality/node limits and artifact structure budgets,
  with redirect-chain length enforced before entry traversal;
- strict TLS EOF handling and non-expanding redaction of every query value from
  exported URL metadata; a query is omitted when placeholders would expand it,
  while the original remains only in in-memory request state;
- opt-in-only recording with process-safe, first-writer-wins content-addressed
  captures; record, replay, and direct body reads share one per-capture lock,
  cap manifest/body/artifact sizes, and verify the manifest, hashes, capture ID,
  content ID, artifact, and body as one binding.

Human-oriented CLI output escapes terminal controls. JSON/JSONL remains
canonical for files and pipes; interactive terminal rendering escapes C1
controls with JSON-valid Unicode escapes.

These are implementation properties, not a claim that every deployment is
immune to SSRF. See the
[security guarantees](https://github.com/ShiroKSH/fetchseal/blob/main/docs/security-guarantees.md),
[threat model](https://github.com/ShiroKSH/fetchseal/blob/main/docs/threat-model.md),
and [residual risks](https://github.com/ShiroKSH/fetchseal/blob/main/docs/residual-risks.md).

## Non-goals

FetchSeal is not a crawler, browser, general HTTP client, network egress
firewall, document converter, model framework, or prompt-injection antivirus.
It does not make remote content trusted. Citation delimiters and trust labels
are metadata for consumers, not a model security boundary.

## Comparison

| Tool category | Primary job |
| --- | --- |
| curl / HTTPX | Transport and HTTP primitives |
| Crawl4AI / Firecrawl | Crawling, browser use, and large-scale extraction |
| Agent egress firewalls | Process or network mediation |
| FetchSeal | Embedded bounded fetch plus a portable citation-ready artifact |

The categories solve different problems. This table does not imply that other
tools are unsafe.

## More

- [Architecture](https://github.com/ShiroKSH/fetchseal/blob/main/docs/architecture.md)
- [Artifact format](https://github.com/ShiroKSH/fetchseal/blob/main/docs/artifact-format.md)
- [Policies](https://github.com/ShiroKSH/fetchseal/blob/main/docs/policies.md)
- [Security policy](https://github.com/ShiroKSH/fetchseal/security/policy)
- [Contributing](https://github.com/ShiroKSH/fetchseal/blob/main/CONTRIBUTING.md)
