Metadata-Version: 2.4
Name: hla-compass
Version: 5.4.0
Summary: Python SDK for HLA-Compass bioinformatics platform - Build powerful modules for immuno-peptidomics analysis
Author-email: Alithea Bio <armanas.povilionis@alithea.bio>
License-Expression: MIT
Project-URL: Homepage, https://alithea.bio
Project-URL: Documentation, https://docs.alithea.bio
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
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: Operating System :: OS Independent
Requires-Python: <3.15,>=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28.0
Requires-Dist: boto3>=1.26.0
Requires-Dist: click>=8.0.0
Requires-Dist: rich>=12.0.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: jsonschema>=4.17.0
Requires-Dist: keyring>=25.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: packaging>=23.0
Provides-Extra: dev
Requires-Dist: build>=1.2.0; extra == "dev"
Requires-Dist: pip-tools>=7.0.0; extra == "dev"
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
Requires-Dist: pytest-mock>=3.6.0; extra == "dev"
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=0.950; extra == "dev"
Requires-Dist: types-requests>=2.28.0; extra == "dev"
Requires-Dist: PyYAML>=6.0.0; extra == "dev"
Requires-Dist: sphinx>=4.0.0; extra == "dev"
Requires-Dist: sphinx-rtd-theme>=1.0.0; extra == "dev"
Provides-Extra: data
Requires-Dist: pandas>=2.2.0; extra == "data"
Requires-Dist: pyarrow>=15.0.0; extra == "data"
Requires-Dist: s3fs>=2026.6.0; extra == "data"
Requires-Dist: xlsxwriter>=3.0.0; extra == "data"
Requires-Dist: polars>=0.20.0; extra == "data"
Provides-Extra: ml
Requires-Dist: scikit-learn>=1.0.0; extra == "ml"
Requires-Dist: torch>=1.10.0; extra == "ml"
Requires-Dist: transformers>=4.20.0; extra == "ml"
Provides-Extra: mcp
Requires-Dist: mcp<2,>=1.28.1; extra == "mcp"
Provides-Extra: authoring
Requires-Dist: mcp<2,>=1.28.1; extra == "authoring"
Requires-Dist: pytest>=7.0.0; extra == "authoring"
Dynamic: license-file

# HLA-Compass Python SDK

[![PyPI version](https://badge.fury.io/py/hla-compass.svg)](https://badge.fury.io/py/hla-compass)
[![Python Versions](https://img.shields.io/pypi/pyversions/hla-compass.svg)](https://pypi.org/project/hla-compass/)

The official Python SDK (Python 3.11–3.14) for developing modules and integrations on the HLA-Compass platform.

Before publishing, choose the default source-upload path or the advanced
custom-image path using the authoritative
[module publishing prerequisite ladder](https://docs.alithea.bio/publishing-prerequisites/).

## 🚀 Quick Start

```bash
# 1. Install
pip install "hla-compass[authoring]>=5.4.0,<6"

# 2. Authenticate
hla-compass auth login --env dev

# 3. Optionally pin a default organization for publish operations
hla-compass auth use-org 00000000-0000-0000-0000-000000000000 --env dev

# 4. Create
hla-compass init my-module --template no-ui
cd my-module

# 5. Run repository-independent source gates
hla-compass validate --strict
pytest
hla-compass mcp schema

# 6. Run the container gate only when this SDK release has the required
# managed runtime/UI-builder image (see "Release-controlled build images")
hla-compass test --input examples/sample_input.json

# 7. Publish (source-upload — the platform builds the container)
hla-compass publish --env dev --scope org --wait
```

Interactive login uses an ephemeral IP-literal loopback callback, CSRF state, and S256
PKCE. The browser callback contains only a short-lived single-use authorization
code; access and refresh tokens are returned directly to the SDK during the
code exchange and then stored in the operating-system keyring (or the
permission-restricted encrypted fallback). The SDK never accepts a token
payload from the loopback URL.

For unattended publishing, create a publish-only API key in the platform
profile and store it as a CI secret. The SDK automatically selects the
API-key machine route when `HLA_API_KEY` is set:

```bash
export HLA_API_KEY="<publish-only-key>"
hla-compass publish --env dev --scope org --wait
```

Do not reuse a data or MCP key: the platform requires `publish` to be the
key's only permission and binds publication and status access to that key's
organization. The generated GitHub workflow maps its repository publish
secret to the canonical `HLA_API_KEY` variable for the CLI. Every
`hla-compass init` scaffold includes it at `.github/workflows/publish.yml`.
That workflow is self-contained and installs the scaffold's exact released SDK
version from PyPI; it does not call or check out the private platform
repository. Do not replace it with a reusable workflow pinned to `main`. A
custom-image reusable workflow is not a public release artifact until it is
hosted in an Actions-accessible repository and identified by a reviewed
full-length commit SHA.

For headless module execution, use a separate developer key with `read` and
`write`; add `delete` only if the integration must cancel runs. The SDK selects
the API-key control plane automatically:

```bash
export HLA_API_KEY="<read-write-developer-key>"
```

```python
from hla_compass import APIClient

client = APIClient(environment="dev")
run = client.start_module_run("MODULE_UUID", parameters={"name": "world"}, mode="async")
result = client.wait_for_module_run(run["run_id"])
```

Developer keys use `/v1/api/module-runs`; bearer sessions use
`/v1/module-runs`. Short-lived keys issued to running modules cannot use either
control plane. Publish-only keys cannot execute modules.

### Explicit Module redeployment

Source publishing remains the normal release workflow: `hla-compass publish
--wait` submits governed source intake and the platform deploys the accepted
Module Version automatically.
Managed source intake first performs platform-owned, constrained static AST
and manifest-schema analysis of the bounded source archive without importing
or executing publisher Python. A successful check persists structured
`mcpEntrypointValidation` evidence, bound to the canonical manifest, source
archive, and final image digest, in the content-addressed publication
attestation. The callback and later publication/run-admission checks require
that matching evidence.

The canonical image build separately installs the declared dependency closure,
copies the module source, and repeats SDK `ModuleValidator` entrypoint checks
with network access disabled as the final numeric non-root runtime identity.
That check imports publisher Python and can execute module-level code even
though it does not invoke native MCP callables. Treat it as a cooperative
build-quality smoke test, not a hostile-code sandbox, security boundary, or
the result proved by `mcpEntrypointValidation`. Missing, non-callable, async,
or signature-incompatible declarations still fail the build before push or
registration.

Native MCP is source-only in this release. If `manifest.mcp.tools` is
non-empty, publish with the default source-upload flow; `hla-compass publish
--image-ref ...` and every image-only compatibility adapter reject the request,
including dry runs. Local `hla-compass validate --strict` remains useful, but
cannot substitute for the platform-owned static analysis and attestation of a
bounded managed source archive.

The compressed source ZIP is limited to 3 MiB by the synchronous publication
transport. Keep datasets, model weights, generated builds, and other large
assets outside the module source tree and access them through governed Catalog
or storage interfaces at runtime. A larger prebuilt artifact without native
MCP capabilities requires the separately governed custom-image publication
path.

Use the following bearer-only surface only when an existing version needs an
explicit operational redeploy:

```python
from hla_compass import APIClient

client = APIClient(environment="dev")  # run `hla-compass auth login` first
receipt = client.deploy_module(
    "MODULE_UUID",
    version="1.2.3",
    deployment_target="auto",
)
deployment = client.wait_for_module_deployment(
    receipt["module_id"],
    receipt["deployment_id"],
    timeout=900,
    poll_interval=5,
)
```

`deploy_module()` returns durable admission with `status="in_progress"` and a
`dispatch_state` of `submitted`, `pending`, or `unchanged`; it does not prove
deployment success. `get_module_deployment()` performs one status read.
`wait_for_module_deployment()` returns only for `deployed`; `failed`,
`cancelled`, and `superseded` raise `APIError` with the platform error message.
API keys and module-run credentials are rejected locally for all three methods.
The deploy request accepts only the existing version selector, target, and
runtime configuration. It never accepts package bytes, an S3/object path, a
container reference, or replacement manifest data: the platform resolves the
exact persisted artifact and scan/schema evidence for that governed Module
Version.

### Pipeline API

The Python client exposes the standalone Pipeline authoring, inspection, and
existing-run lifecycle:
`list_pipelines`, `get_pipeline`, `update_pipeline`, `delete_pipeline`, preset
add/read/default/delete methods, and run start/status/tasks/logs/cancel methods.
A params file supplies base values and the optional inline `parameters` mapping
overrides top-level keys. Local `params_file` and S3 `params_file_uri` are
mutually exclusive with each other, but either may be combined with inline
overrides or a `samplesheet` override. Run submission also accepts
`output_uri`, `user_config_uri`, `priority`, `tags`, `resource_profile`,
`nextflow_profile`, `on_demand`, and `resume_from_run_id`. Submission reserves
ACT from the selected resource profile; a completed run consumes that
reservation and anything else refunds it.

Pipelines whose response has `launchedViaModuleOnly: true` are internal
artifacts. Manage them through their owning Module; direct Pipeline mutation
endpoints reject them, and Module-backed dispatch reaches the same release
gate.

`hla-compass test` is offline by default and does not forward host credentials
or selected catalog state. Non-pipeline templates build and exercise a local
container; pipeline templates exercise the configure handler in-process. Use
`hla-compass test --live ...` only when the test intentionally calls the
authenticated platform; CI jobs that require live integration must opt in with
that flag explicitly.

## Request access

Prospective users can submit a durable access request for platform-admin review:

```python
from hla_compass.auth import Auth

request = Auth().request_access(
    "user@example.org",
    "Example",
    "User",
    "Example Bio",
    environment="dev",
    position="Scientist",
    field_of_interest="TCR",
)
```

This queues a request; it does not create an account or grant organization
membership. Accounts are provisioned through administrator invitations.
`Auth.register()` and `Auth.developer_register()` remain as compatibility
methods but fail locally with request-access and invitation guidance instead of
calling retired endpoints.

### MFA challenge and recovery

`Auth.login()` can return `challenge="MFA_REQUIRED"`, the opaque `session`, and
`recovery_available`. Complete a normal authenticator challenge with
`Auth.complete_mfa(email, session, six_digit_code)`, which returns and stores
the authenticated token payload.

Offer a saved recovery code only when `recovery_available` is true:

```python
reset = Auth().complete_mfa_recovery(email, session, recovery_code)
assert reset["mfa_reset"] is True
assert reset["reauthentication_required"] is True
```

Recovery deliberately returns no tokens. It globally signs out the account,
disables the lost authenticator, and revokes the recovery-code batch. Call
`Auth.login()` again, then enroll a new authenticator before attempting
privileged mutations.

This README is intentionally concise. The public documentation portal is
[docs.alithea.bio](https://docs.alithea.bio); every generated module also ships
with a version-aligned `SKILL.md` and linked `DATA_ACCESS.md` reference.

## 📚 Docs Model

- [Public documentation](https://docs.alithea.bio): SDK, module-authoring, API, and release workflows.
- `SKILL.md` generated by `hla-compass init`: canonical in-module authoring and runtime reference for developers and AI assistants.
- `DATA_ACCESS.md` generated by `hla-compass init`: companion typed-data and scoped-storage contract linked from `SKILL.md`.
- `INTEGRATIONS.md` generated by `hla-compass init`: copy-ready catalog, Python API, REST API, and MCP integration reference.
- `AGENTS.md` generated by `hla-compass init`: a bounded Codex loader that routes agents to the managed guidance without private repository access while preserving project-specific instructions.
- `CLAUDE.md` generated by `hla-compass init`: short in-module orientation that points back to `SKILL.md`.
- `UI_EXTENSION.md` / `MCP_CAPABILITIES.md` when required by a composite manifest: feature overlays that preserve both the compute and UI/native-MCP contracts.

---

## 🤖 AI-Assisted Development

Every module scaffolded by `hla-compass init` includes a documentation set for
both human developers and AI coding assistants:

| File | Purpose |
|------|---------|
| **`SKILL.md`** | Canonical in-module authoring and runtime reference. **Point your AI assistant here first.** |
| **`DATA_ACCESS.md`** | Companion typed-data, Catalog Version, storage, and ingestion-boundary reference linked from `SKILL.md`. |
| **`INTEGRATIONS.md`** | Catalog-selection, Python API, REST API, and MCP integration examples linked from `SKILL.md`. |
| **`AGENTS.md`** | Bounded Codex loader; existing project-specific text is preserved around the managed discovery block. |
| **`CLAUDE.md`** | Thin managed loader/orientation that directs Claude to `SKILL.md` and any linked feature references; it does not duplicate the template contract. |
| **`UI_EXTENSION.md` / `MCP_CAPABILITIES.md`** | Conditional feature references for compute modules: React UI authoring, or native MCP tools. |

> **Tip:** When using an AI coding assistant (Claude, Copilot, etc.), ensure it reads
> `SKILL.md` and follows its links to `DATA_ACCESS.md` and `INTEGRATIONS.md` in
> your module directory. Together they provide the version-aligned contract
> without requiring private repository context. Production readiness still
> requires domain tests and verification in the target environment.

### Refresh an existing module's SDK guidance

After installing a newer SDK, inspect the module's generated guidance before
updating it:

```bash
hla-compass skill check [MODULE_DIR]
hla-compass skill update [MODULE_DIR]
```

`skill update` refreshes the SDK-managed bundle: `SKILL.md`, `DATA_ACCESS.md`,
`INTEGRATIONS.md`, the concise `CLAUDE.md` loader, and any manifest-required
`UI_EXTENSION.md` / `MCP_CAPABILITIES.md` feature references. It also creates
or refreshes a bounded block in `AGENTS.md` while preserving existing
project-specific instructions. Put
module-specific instructions only between the
`hla-compass-user-guidance:start` and `hla-compass-user-guidance:end` markers;
the updater preserves that block across releases. Edits outside that block, or
unrecognized legacy guidance, fail closed. Review those files and use
`hla-compass skill update [MODULE_DIR] --force` only for an intentional
migration. Existing files are backed up by content hash under
`.hla-compass/backups/sdk-guidance/` by default; that private SDK state is
ignored from Git, source archives, and SDK-generated Docker build contexts.

The same inspection and update operations are available to Python tooling:

```python
from hla_compass import inspect_module_skill, update_module_skill

status = inspect_module_skill("path/to/module")
if not status.current:
    result = update_module_skill("path/to/module")
```

These operations update documentation only; they do not rerun `init`, replace
module source, publish a module, or prove that a deployment works.

They also verify `backend/requirements.txt`. A `runtime-gap` status is
non-zero unless the module pins the exact installed SDK release (for example
`hla-compass==<installed-sdk-version>`). The guidance updater does not silently change executable
dependencies: update that pin deliberately, regenerate
`backend/requirements.lock.txt` when present, then rerun `skill check`, strict
validation, and tests.

---

## 🛠️ CLI Entry Points

| Command | Description |
|:--------|:------------|
| `init` | Scaffold a new module (includes `SKILL.md` reference guide) |
| `skill` | Check or update an existing module's SDK-managed guidance bundle |
| `validate` | Validate module structure and manifest |
| `test` | Run a local module smoke execution (containerized except pipeline configure tests) |
| `dev` | Run the interactive local rerun loop |
| `serve` | Serve the UI template locally |
| `publish` | Upload module source to the platform for server-side build and registration |
| `publish-status` | Inspect or watch module intake status |
| `auth` | Manage platform login and keys |
| `mcp` | Print MCP schema or run a local MCP server for the current module |

`hla-compass auth logout` attempts authenticated platform logout with the
stored refresh token before removing local credentials and organization
context. It exits successfully only when there was no local user session or the
platform returns `refreshSessionsRevoked: true`. Local state is still cleared
when the platform cannot confirm revocation; that case is reported as a warning
with exit code 2 so scripts do not mistake local cleanup for confirmed remote
refresh-session revocation. Already-issued platform ID JWTs remain valid until
their normal expiry because API Gateway validates them statelessly.

`hla-compass mcp serve` is an offline local tool server by default. After
authenticating, pass `--live` to exercise Catalog/API reads. Hosted MCP tool
names and execution-policy metadata are authoritative. `mcp schema` previews
the local manifest-derived input and output schemas using the same canonical
object-contract shape as the hosted Module descriptor; it does not reproduce
host-only policy or authorization metadata. The stdio server keeps its
protocol host free of publisher imports: every primary and native tool call
runs in a fresh child interpreter rooted at the directory containing
`manifest.json`. Embedders exposing native tools must likewise construct
`MCPModuleServer(None, manifest_path=...)`; passing a pre-imported publisher
class is rejected because its import may already have changed host process
state.

---

## 🔧 Local SDK Development

When iterating on the SDK itself, use the `HLA_COMPASS_SDK_PATH` environment variable
so that `dev`/`test`/`serve` commands pick up either your local checkout or a
built wheel:

```bash
export HLA_COMPASS_SDK_PATH=../sdk/python
hla-compass dev
hla-compass test --input examples/sample_input.json

# Repository-independent clean-wheel form:
export HLA_COMPASS_SDK_PATH=/absolute/path/to/hla_compass-5.2.0-py3-none-any.whl
```

For an artifact-reproducible authored module/SDK Python dependency closure,
generate and commit a complete hash lock after every dependency or SDK pin
change. Run the exact managed-build-image command in the generated module's
`INTEGRATIONS.md` under **Reproducible Python dependencies**. It selects the
manifest's digest-pinned Python 3.13 Linux build image. Do not run the release
lock directly on macOS or Windows: those resolvers can omit Linux-only
dependencies even when every emitted entry has a hash.

With that lock, released SDK wheels are installed by the hash-verified lock;
an explicitly supplied local SDK artifact is installed `--no-deps` before the
filtered lock supplies its closure. The build validates selected SDK extras and
runs `pip check`. Index installs are wheel-only, so missing target wheels fail
closed rather than executing sdist build backends. A scaffold without the lock
remains functional for immediate development, but the CLI warns that index
resolution at build time is not artifact-reproducible.

The scanned, digest-pinned base owns OS patches, packaging tools, and Lambda's
runtime client; generated child images do not upgrade those inputs live. A
custom compatible base must already supply Python and pip, plus
`awslambdaric` for Lambda. The module lock controls the authored module/SDK
closure while the exact base digest controls platform inputs. A local SDK
source directory is compiled in the released managed module-runtime builder,
independent of the final/custom base, so that base does not need SDK build
backends such as `setuptools` or `wheel`.

---

## Release-controlled build images

The SDK and deployed source-build service read the same packaged image-release
manifest, `hla_compass/module_build_images.json`. Production builds accept only
exact `image@sha256:<digest>` references. If a managed runtime or UI builder has
not passed its release gates, its manifest entry is intentionally empty and the
affected build fails before Docker starts with replacement-publication guidance.

At the current release boundary:

- Lambda source builds use the released, digest-pinned platform Lambda runtime
  derived from the signed/scanned Wolfi module runtime. Its release adds the
  hash-locked AWS Lambda Runtime Interface Client, scans both base
  architectures, then signs and attests the exact multi-architecture digest.
  The pin becomes release-ready only after the no-live-upgrade SDK generator
  also builds and blocking-scans representative final images on both targets.
- Fargate and Batch source builds use the released, signed and attested
  multi-architecture Wolfi runtime pinned by exact OCI digest.
- UI source builds use the released, signed and attested Node 24 builder pinned
  by exact OCI digest. This enables the build and validation stage; hosted UI
  execution remains disabled behind the separate

An exact approved image can be supplied to local build commands with
`--base-image` or `--ui-build-image`. Mutable tags are rejected by default. The
only mutable-tag exception requires both
`HLA_COMPASS_ALLOW_MUTABLE_BUILD_IMAGES_LOCAL_ONLY=true` and
`HLA_COMPASS_BUILD_CONTEXT=local|offline|test`; it is never a production
release mechanism. Source ZIPs omit root `Dockerfile`/`Dockerfile.hla` files,
generated/cache directories, and common credential filenames using a
case-insensitive policy; an included symbolic link is rejected rather than
followed. This filename policy is defense in depth, not a secret scanner. Keep
all credentials outside the module tree and scan the repository before
publishing. Managed intake rejects directly supplied build recipes. Native
tools and custom operating-system layers belong in the signed custom-image
flow.

---

## 💎 Key Features

- **Module-first CLI**: Scaffold, test, and publish with a single toolchain.
- **Source-upload publishing**: `hla-compass publish` uploads source; the
  platform builds, scans, and registers the container. See the linked
  prerequisite ladder before choosing the advanced custom-image path.
- **Data helpers**: Storage + data access helpers for module runtimes.
- **Local dev loop**: Containerized `dev`/`serve`/`test` flow for the packaged
  runtime contract; environment-backed behavior still requires live verification.

The CLI uses the active org for the selected environment by default, or `--org-id` to override it.

Direct ZIP registration is not a publication Interface. SDK 5 retains the
published `APIClient.upload_module(module_path, module_name, version)`
signature only as a local migration stub: every call raises `APIError` with
status code 410 before reading the path or making an HTTP request. Existing
integrations must instead call
`APIClient.publish_module_source(manifest=..., source_zip=..., scope="org",
idempotency_key="<stable-retry-key>")`
or invoke
`hla-compass publish --env dev --scope org --idempotency-key <stable-retry-key> --wait`
from the Module source directory. Both paths enter the governed asynchronous build, immutable
digest, signature, and security-scan intake before a Module Version exists.
The retry key must contain 1-256 exact printable ASCII characters. Reusing it for the
same organization, manifest, scope, and source bytes returns the original build;
reusing it for different evidence returns HTTP 409 and never overwrites the
source archive. Re-signing unchanged content does not cause a conflict: the
platform verifies the signature, normalizes only its randomized RSA-PSS bytes,
and still binds the signed manifest and signer metadata.
Manifest signing canonicalization excludes signature metadata only at the
manifest root and excludes the platform-owned root `integrity` field. A
reserved signature-metadata key below the root is rejected instead of being
left unsigned, including when an org-scoped manifest otherwise omits a
signature. Nested `integrity` fields remain developer-authored content and are
covered by the signature; changing one invalidates verification.

## Module Runtime Credential Boundary

Published module code runs with a short-lived key bound to one module run and
organization. Inside `execute()`, use typed catalog helpers, read-only catalog
storage, `self.storage` for run outputs, and current-run progress/callbacks. The
run key is not a logged-in control-plane session: it cannot list/start/cancel
runs, inspect status/logs/results, publish modules, or mutate dataset-version
state. The `Module` composition/polling/result helpers raise
`ModuleCapabilityError` locally in this mode.

Hosted module roles have no direct S3 permission. `self.storage` uses the run
token to ask the platform storage broker for narrowly scoped operations under
the current run's private `files/` namespace, then transfers bytes through
short-lived pre-signed URLs without sending the run token to object storage.
Use `save_file`/`save_json`/`save_csv`, `load`/`load_json`/`load_text`,
`list_files`, `delete_file`, and `create_download_url`; pass logical keys such
as `results/output.json`, never bucket names, `s3://` URIs, or another run's
prefix. Direct S3 remains an explicit local-development compatibility path
when `HLA_COMPASS_RESULTS_BUCKET` is configured without a module-run token.

Use a standalone `APIClient()` with either `hla-compass auth login` or an
appropriately scoped developer API key for Module Run control outside
`execute()`. Deployment and governed ingestion remain bearer-only.

## Personal Account Data

Bearer-authenticated users can request a time-limited export of their own
account data without routing the export bytes through Python:

```python
from hla_compass.client import APIClient

client = APIClient(environment="dev")
export = client.request_personal_data_export(
    export_format="zip",
    date_range="last90days",
    include_jobs=False,
    include_results=True,
)
print(export["download_url"])  # signed URL; expires after 15 minutes
```

Run `hla-compass auth login --env <environment>` first. Personal-data exports
are intentionally unavailable to API keys and module-run credentials. The SDK
returns the signed-URL metadata and does not download personal-data bytes.
Result locations and metadata can be selected independently of module-run
history; job rows never include those locations implicitly.

## Compute Types

Public module manifests use these compute types:

- `lambda`
- `fargate`
- `batch`
- `pipeline` (pipeline-ui / Nextflow definitions; authoring and publication are available, while execution is release-gated)

`docker` remains accepted only as a legacy publish alias and is normalized to `fargate`.

## Scientific Helper Notes

The convenience helpers `get_hla_alleles()`, `get_hla_frequencies()`, and
`get_protein_coverage()` are implemented as typed REST calls in SDK `3.0.0+`.
They no longer switch implicitly between direct database access and REST.

Migration guidance:

- High-level SDK callers now need a reachable HLA-Compass API endpoint for these helpers.
- API-key authenticated clients continue to work; the SDK now targets `/v1/api/data/...` typed endpoints instead of issuing raw SQL on the caller's behalf.
- Plain JWT user sessions now work through `/v1/data/...` typed endpoints.
- Prefer a canonical Catalog UUID input and call
  `catalog_api = client.for_catalog_id(catalog_id)` externally or
  `self.bind_catalog_id(catalog_id)` inside `execute()`. When only exact keys
  are available, `for_catalog(provider, catalog)` and
  `bind_catalog(provider, catalog)` remain supported. These methods keep typed
  reads plus Catalog storage on the same exact identity and never fall back to
  a prior configured Catalog. Binding does not select a Catalog Version; pass a
  separate explicit Version UUID to reproducible reads.
- `self.data.sql.query(...)` is a privileged, read-only platform-administrator
  helper. It is not available to API keys or module run tokens; runtime modules
  should use typed SDK helpers instead.
- Direct SQL writes are disabled. Catalog publication goes through the governed
  ingestion workflow so source snapshots, attempts, lineage, and finalization
  remain auditable.
- The legacy `catalog-import` module template is retired and is not scaffolded
  for new modules. `create_catalog_import_upload()` is also retired.
- For normal local files, use `upload_catalog_import_file()`. It streams raw and
  per-part hashes, follows the server-issued fixed-size plan, retries transient
  part transfers, completes with exact ETags, and optionally waits until the
  verifier marks the immutable object version `claimed`.
- The lower-level governed control-plane upload contract remains exposed through
  `initialize_catalog_import_upload()`, `sign_catalog_import_upload_parts()`,
  `complete_catalog_import_upload()`, `abort_catalog_import_upload()`, and
  `get_catalog_import_upload()`. Completion returns
  `uploaded_unverified`; callers must poll until `claimed` before submitting
  the object to Catalog Ingestion. The deployed API/verifier wiring must be
  enabled by the platform—SDK availability alone does not make the workflow
  operational.
- Bearer-authenticated org administrators can then use
  `submit_catalog_ingestion()`, `get_catalog_ingestion()`,
  `cancel_catalog_ingestion()`, and `retry_catalog_ingestion()`. The API is
  default-off behind `CATALOG_INGESTION_ENABLED`; API-key and module-run
  credentials remain denied. Cancel/retry require the latest top-level job
  `stateVersion`. A `retry_idempotency_key` must differ from the original
  submit key; repeating it may return the prior retry with `outcome=replayed`.

Control-plane Python example (the SDK resolves each claimed upload UUID to the
server-returned canonical source URI; callers do not assemble S3 paths):

```python
upload = client.upload_catalog_import_file(
    catalog_id,
    "samples.parquet",
    idempotency_key="upload-2026-07-10",
    wait_until_claimed=True,
)
job = client.data.ingestion.submit(
    catalog_id,
    sources=[{"uploadId": upload["uploadId"], "targetTable": "samples"}],
    idempotency_key="import-2026-07-10",
)
state = client.data.ingestion.status(catalog_id, job["jobId"])
```

Equivalent CLI status/control commands:

```bash
hla-compass data catalog create \
  --provider-key alithea-bio \
  --catalog-key research \
  --schema-name scientific \
  --label "Research" \
  --source-table samples \
  --domain peptidome \
  --yes
hla-compass data ingestion upload CATALOG_ID samples.parquet \
  --idempotency-key upload-2026-07-10 \
  --yes
hla-compass data ingestion submit CATALOG_ID \
  --source UPLOAD_ID:samples \
  --idempotency-key import-2026-07-10 \
  --yes
hla-compass data ingestion status CATALOG_ID JOB_ID
hla-compass data ingestion cancel CATALOG_ID JOB_ID \
  --job-state-version 2 --yes
hla-compass data ingestion retry CATALOG_ID JOB_ID \
  --job-state-version 3 \
  --retry-idempotency-key retry-2026-07-10-1 \
  --yes
```

`predict_hla_binding()` is also implemented, but it is a wrapper over an async
module run and requires a configured binding module id
(`HLA_BINDING_MODULE_ID` or `hla_binding_module_id` in SDK config).

---

## Agent clients and the hosted MCP platform

Install the MCP extra and authenticate with the SDK before configuring Codex,
Claude Code, or another compatible MCP client:

```bash
python -m pip install 'hla-compass[mcp]>=5.4.0,<6'
hla-compass auth login --env dev
```

No public remote Codex or Claude Code marketplace release is available yet;
external users should configure the standalone stdio gateway described below.
The repository-local plugin manifests are maintainer validation artifacts.
Those manifests launch the bare `hla-compass` executable. For GUI clients, prefer
`pipx install 'hla-compass[mcp]>=5.4.0,<6'`, ensure the pipx apps directory is
on the client's `PATH`, and restart the client. If a project virtual
environment is required, launch the client from that activated environment or
configure a standalone MCP server with the absolute path to its
`hla-compass` executable.

Configure a compatible MCP client to launch the executable `hla-compass` with
arguments `mcp`, `gateway`. The local gateway reuses the SDK credential store,
so client configuration contains no credential value. Set `HLA_COMPASS_ENV` to
`dev`, `staging`, or `prod` only when intentionally overriding the SDK's
selected environment.

Catalog Import MCP tools require an interactive org-admin bearer session.
Multipart completion remains `uploaded_unverified`; only a later `claimed`
status proves exact-version verification. `submit_catalog_ingestion` accepts
only claimed upload UUIDs and replace mode; poll `get_catalog_ingestion` and
use its top-level `jobStateVersion` for confirmed cancel/retry operations.
Use a retry key distinct from the original submit key; repeating the same retry
key may return `outcome=replayed`. Append ingestion and direct Catalog Version
publication are unavailable.

The hosted MCP `query_data` tool is retained only as a JWT
`platform_admin`-only, read-only compatibility exception with relation
allowlists, request-scoped RLS, timeout, pagination, and audit controls. Prefer
typed tools; API keys and module run tokens cannot use this exception.

---

## 📖 Advanced Documentation

- **[Public documentation](https://docs.alithea.bio)** – SDK, module workflow, and API reference.
- **Generated documentation set** – Version-aligned `SKILL.md`, `DATA_ACCESS.md`, and concise `CLAUDE.md` orientation.
- **`hla-compass --help`** – Installed command and subcommand reference.

---

## 🤝 Support and security

Use the [Alithea Bio website](https://alithea.bio) to contact the team. Do not
send credentials or sensitive scientific data in an initial support message.
For a security report, request a private channel before sharing technical
details.
