Skip to content

Module Publishing Prerequisites

This is the authoritative prerequisite ladder for publishing an HLA-Compass module with SDK 5.9.2 and its matching platform release. Scientific modules require their own tests after rebuilding; installing the SDK does not establish that a scientific workflow has completed successfully.

Start with Tier 1. Use Tier 2 only when the module cannot use the platform-managed runtime image.

Baseline for Both Tiers

  • Python 3.11 through 3.14.
  • An invited HLA-Compass account with membership in the target organization.
  • The current SDK release installed in an isolated environment.
  • A module that passes hla-compass validate and its domain tests.

Docker is required to generate the Linux dependency lock with hla-compass lock and for containerized local testing/development. A fresh scaffold needs that lock before publishing. Once a matching lock has been generated and committed by an author or CI, Docker is not required merely to submit its source archive. Install the authoring extra when running scaffold tests locally.

Tier 1: Source Upload (Default)

Use this tier unless the module needs a custom system runtime or a prebuilt image. The platform generates the canonical build recipe, pushes the final image to managed ECR, waits for the blocking Inspector scan, records platform-owned source-build evidence, and registers the digest. Source upload does not accept a caller-supplied Dockerfile.

Managed source publication requires a complete artifact-hashed backend/requirements.lock.txt that is current with backend/requirements.txt; missing, unhashed, stale, or incomplete locks are rejected before Docker starts. Generate it with hla-compass lock from the module directory; the scaffold's INTEGRATIONS.md explains the target runtime. Only non-managed local authoring may warn and synthesize an unlocked install for immediate development.

Modules that declare manifest.mcp.tools must also follow the native-MCP finite handler source contract. For an existing module, hla-compass skill update refreshes guidance but does not perform the required executable-source and manifest migration.

Managed source intake performs two distinct checks. The security-relevant check is platform-owned, constrained static AST and manifest-schema analysis of the bounded source archive. It does not import or execute publisher Python. A successful check records structured mcpEntrypointValidation evidence bound to the canonical manifest, source archive, and digest-pinned image. The managed source callback accepts that evidence only from the content-addressed CodeBuild publication attestation. Publication, run admission, and later lifecycle transitions continue to require the matching persisted evidence; a source archive marker alone is not publication authority.

Separately, after installing the declared dependencies and copying the module source, the canonical image build repeats ModuleValidator entrypoint checks offline as the final numeric non-root runtime identity, with HOME and language caches redirected to /tmp. This imports publisher Python and can therefore execute module-level code even though native MCP callables are never invoked. It is a cooperative build-quality smoke test—not a hostile-code sandbox, security boundary, or the fact proved by the attestation. Missing, non-callable, async, or signature-incompatible declarations still fail the build before the image can be pushed or registered.

Release availability is intentionally fail-closed. The current release enables Lambda, Fargate, Batch, and with-ui source builds with reviewed exact-digest runtime and UI-builder pins. The platform loads a published UI only after its trust checks and integrity hash are available; see UI modules. Use Tier 2 only when the workload requires a custom image; do not use it to bypass a failed security gate.

You do not need:

  • a container registry or GHCR namespace;
  • registry pull credentials;
  • Cosign keys or GitHub OIDC signer trust; or
  • permission to push container images.

For a manual dev/staging publish, install the exact TestPyPI candidate with dependencies from PyPI, then authenticate interactively:

python -m venv .venv
source .venv/bin/activate
python -m pip download --index-url https://test.pypi.org/simple/ --no-deps --only-binary=:all: --dest sdk-wheel "hla-compass==5.9.2"
python -m pip install "hla-compass[authoring]==5.9.2" --index-url https://pypi.org/simple/ --find-links sdk-wheel
hla-compass auth login --env dev
hla-compass init peptide-summary --template lambda
cd peptide-summary
python -m pip install -r backend/requirements.txt
hla-compass lock
hla-compass validate --strict
python -m pytest
hla-compass test --input examples/sample_input.json
hla-compass publish \
  --env dev \
  --scope org \
  --idempotency-key peptide-summary-1.0.0-release-1 \
  --wait

For CI, create a Module publishing API key in the HLA-Compass profile, store it as the repository secret HLA_COMPASS_API_KEY, and use the .github/workflows/publish.yml included in every current scaffold. The key is publish-only and bound to one organization; it must not be reused for data or MCP access.

Verify the key before relying on it: hla-compass auth status --check performs a real authenticated call and exits non-zero if the credential cannot be used. Plain auth status only prints a table and always succeeds, so it is not a gate. The shipped workflow uses --check.

The publish is successful only when the CLI reports a terminal successful intake status. An upload receipt or local image build is not proof that the version is deployable.

A build can outlast the CLI wait period. --wait gives up after its --timeout and exits 75, which means the client stopped watching, not that the publish failed; a genuine failure exits 1. On 75, poll hla-compass publish-status --env <env> <publishId> rather than republishing.

Tier 2: Custom Image (Advanced)

New Fargate and Batch custom images must declare USER 1000:1000, a canonical absolute non-root WORKDIR, and exactly one writable volume at /tmp. Intake checks the image filesystem: the working directory and ancestors must be real, traversable directories; /tmp must be writable and traversable by that user. The deployed root filesystem is read-only. Use the generated SDK Dockerfile as the contract and move scratch/cache/output writes to /tmp; adding USER to an otherwise incompatible image is insufficient. Publication rejects incompatible images instead of silently rewriting them. This does not retrofit historical definitions or change the existing external Nextflow runner.

Use this tier only when Tier 1 cannot supply the runtime required by the module. It adds an external image supply chain and therefore requires all of the following:

  • an organization-approved registry namespace such as ghcr.io/acme-bio/*;
  • a dedicated machine pull credential configured in HLA-Compass for that namespace;
  • an approved github_actions_oidc signer policy matching the source repository and workflow identity;
  • a GitHub Actions job with contents: read, packages: write, and id-token: write; and
  • an SDK manifest-signing RSA keypair. The default location is ~/.hla-compass/keys/{private,public}.pem (or $HLA_COMPASS_CONFIG_DIR/keys/). Generate it once, when missing, with the CLI --generate-keys option. Store private.pem in an approved secret manager or encrypted backup with restricted access, retain public.pem with the release records, and never commit either key; and
  • the same organization-bound, publish-only HLA-Compass API key used by Tier 1 CI.

For a reviewed manual custom-image release, use an immutable digest and run the platform preflight before publication:

IMAGE_REF="ghcr.io/acme-bio/peptide-summary@sha256:<digest>"

# Creates the SDK manifest-signing keypair only when it is missing.
hla-compass verify-image \
  --env dev \
  --image-ref "$IMAGE_REF" \
  --scope org \
  --generate-keys

# Reuses that keypair; the verified digest is the published digest.
hla-compass publish \
  --env dev \
  --image-ref "$IMAGE_REF" \
  --scope org \
  --idempotency-key peptide-summary-1.0.0-image-release-1 \
  --wait

Tier 2 does not support native MCP capabilities. A custom-image request whose manifest contains a non-empty mcp.tools array is rejected with UNSUPPORTED_PUBLICATION_PATH, including dry runs. The canonical request, legacy container and superuser adapters, asynchronous intake, callback, and later publication/run-admission checks all fail closed on this boundary. Use Tier 1 source upload for every module that declares a native MCP tool.

The reason is deliberate: an image-only request does not provide the bounded managed source input required for platform-owned static AST/schema analysis, and the platform does not execute arbitrary custom-image code during privileged intake. It therefore cannot produce the required native-MCP attestation. Running hla-compass validate --strict against the exact source remains a useful authoring check, but it does not authorize a Tier 2 native-MCP publication. Signature, manifest-signature, mirroring, SBOM, and blocking image-scan gates still apply to eligible Tier 2 images; none substitutes for the managed-source evidence.

If the preflight is intentionally performed elsewhere, the first publish may use --generate-keys instead. The option creates missing keys; it does not rotate an existing pair. A CI workflow that generates keys on an ephemeral runner must persist the private key in an approved secret store when signer continuity or later reproduction is required.

No custom-image reusable workflow is currently published for external callers. The platform workflow repository is private and does not currently grant cross-repository Actions access, so a caller cannot load it; a mutable @main reference would not be an acceptable release boundary even if access were enabled. Until a reviewed workflow is released from an accessible repository and identified by its full-length commit SHA, use Tier 1 or a separately reviewed caller-owned Tier 2 workflow that installs one exact released hla-compass version from PyPI. Do not check out or install arbitrary platform repository source in a job holding registry, OIDC, or publish credentials.

Do not use a personal registry token or a developer password as a CI credential. Registry access must use a dedicated machine identity, and module publication must use the publish-only platform key.

Choosing a Tier

Requirement Tier 1 source upload Tier 2 custom image
Platform-managed container build and scan Yes No
GHCR or another approved registry No Yes
Registry machine pull credential No Yes
GitHub OIDC signer trust No Yes
SDK manifest-signing keypair No Yes
Platform-owned attested static AST/schema validation Yes No
Offline non-root ModuleValidator import smoke Cooperative quality check Not run during image intake
Native MCP (manifest.mcp.tools) Supported with attested validation Rejected
Publish-only HLA-Compass API key for CI Yes Yes
Interactive HLA-Compass login for manual publish Yes Optional

If there is uncertainty, choose Tier 1. Moving to Tier 2 is an organization and security-policy decision, not a normal scaffold requirement.