Pack Sources
Automatically sync packs from your own Git repositories and OCI registries into your Scrydon installation.
Pack sources let your developers push packs to infrastructure they already control — a Git repository or an OCI registry — and have your Scrydon installation pick them up automatically on a schedule. No inbound traffic, no manual uploads for every release.
When to use pack sources vs. manual upload
Use pack sources when you have developers who push pack updates from CI and want those updates to land in Scrydon without an administrator running a manual upload for each release. Use manual upload for one-off testing, air-gapped environments, or packs with no automated publish step.
How It Works
Your Scrydon installation runs a reconciler that polls each registered source on a configurable interval (default 5 minutes, minimum 30 seconds). On each tick it:
- Fetches the
scrydon.yamlcatalog file from your source. - Compares it against the previously installed versions.
- For each new or changed entry: fetches the artifact, verifies its signature, and installs it through the same pipeline as a manual upload.
- Records the result — success or detailed failure reason — in the source's run history.
The reconciler is pull-only. Your CI pipeline never needs inbound access to your Scrydon cluster.
The source catalog wins
The scrydon.yaml catalog file is the source of truth for which packs appear in your organization's catalog. If an administrator retires a source-managed pack from the catalog UI, the next sync restores it as long as it is still listed in scrydon.yaml — the same way re-uploading a retired pack manually brings it back. To remove a source-managed pack permanently:
- remove its entry from the source's
scrydon.yaml, or - disable (or delete) the source itself.
Retiring is still useful for manually uploaded packs (no source manages them, so they stay retired) and as a temporary hide for source-managed packs between syncs.
Choosing a Source Type
| Source type | Best for |
|---|---|
| Git | Teams that version pack contents directly in a Git repository and don't want to run a container registry |
| OCI | Teams that publish pack artifacts as OCI images (e.g. to GHCR) as part of their release pipeline |
You can register multiple sources of either type per organization.
The scrydon.yaml Catalog File
Every source is described by a single scrydon.yaml file at a configurable path in your repository or registry. This file is the source of truth for which packs should be installed and at what version.
apiVersion: scrydon.io/v1
kind: PackCatalog
packs:
- id: example.sample
version: 1.0.0
artifact:
kind: git-tar
ref: main
path: packs/sample
signature:
kind: none
- id: example.fraud
version: 1.2.0
artifact:
kind: oci
ref: ghcr.io/example/scrydon-fraud@sha256:abc123def456...
signature:
kind: cosign-keyless
certificateIdentityRegexp: "https://github.com/example/.*"
certificateOidcIssuer: "https://token.actions.githubusercontent.com"Pack catalog fields
| Field | Required | Description |
|---|---|---|
id | Yes | Unique pack identifier, dotted lowercase (e.g. acme.fraud). Combined with version it identifies a pack installation. |
version | Yes | Semver string. The reconciler keys on this field — a release is only picked up when this entry is bumped, even if pack.json and the artifacts changed. See Pack versioning for the full release checklist. |
artifact.kind | Yes | git-tar or oci. |
artifact.ref | Yes | For git-tar: the branch, tag, or commit ref to check out. For oci: the full image reference — prefer @sha256:… digests over mutable tags. |
artifact.path | git-tar only | Subdirectory inside the repository to package. |
signature.kind | Yes | cosign-keyless, cosign-key, or none. |
Unknown keys in scrydon.yaml are rejected. Typos in field names cause a parse_failed error — check the source's run history for details.
Publishing from CI
Git source layout
For a Git source, your repository contains the scrydon.yaml catalog alongside your pack directories. The reconciler packs the declared subdirectory at the configured ref into a .scrydon-pack.tar.gz on the fly.
Minimal layout:
my-packs/
├── scrydon.yaml # Pack catalog
├── packs/
│ └── fraud/ # Pack directory — each has a pack.json
│ ├── pack.json
│ └── ontology/
│ └── manifest.json
└── .github/
└── workflows/
└── validate.yml # Validates scrydon.yaml on every PRValidate scrydon.yaml on pull requests so catalog errors are caught before they reach your Scrydon installation:
# .github/workflows/validate.yml
name: validate-catalog
on:
pull_request:
paths: ['scrydon.yaml', 'packs/**']
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- name: Validate catalog schema
run: |
bunx @scrydon/sdk-authoring sources validate scrydon.yamlOCI source layout
For an OCI source, your CI pipeline builds a .scrydon-pack.tar.gz for each pack, pushes it as an OCI artifact, signs it with cosign, and updates the scrydon.yaml catalog (also pushed as an OCI artifact).
Your workflow needs cosign for signing and oras for pushing generic OCI artifacts:
- uses: sigstore/cosign-installer@v3
- uses: oras-project/setup-oras@v1bunx @scrydon/sdk-authoring pack build packs/fraud \
--out dist/fraud-${{ github.ref_name }}.tar.gzoras push ghcr.io/${{ github.repository_owner }}/scrydon-fraud:${{ github.ref_name }} \
--artifact-type application/vnd.scrydon.pack.v1.tar.gzip \
dist/fraud-${{ github.ref_name }}.tar.gz:application/vnd.scrydon.pack.v1.tar.gzipCOSIGN_EXPERIMENTAL=1 cosign sign --yes \
ghcr.io/${{ github.repository_owner }}/scrydon-fraud:${{ github.ref_name }}No secrets needed — cosign uses GitHub Actions OIDC automatically when id-token: write permission is granted.
Resolve the digest and update scrydon.yaml, then push it as the :catalog tag:
DIGEST=$(oras manifest fetch --output - \
ghcr.io/${{ github.repository_owner }}/scrydon-fraud:${{ github.ref_name }} \
| jq -r '.config.digest // .digest')
sed -i "s|REPLACE_WITH_DIGEST|$DIGEST|" catalog/scrydon.yaml
oras push ghcr.io/${{ github.repository_owner }}/scrydon-catalog:catalog \
--artifact-type application/vnd.scrydon.catalog.v1+yaml \
catalog/scrydon.yaml:application/vnd.scrydon.catalog.v1+yamlFull working examples are in the examples/pack-sources/ directory of the Scrydon SDK repository.
Registering a Source via the Settings UI
Go to Settings > Platform > Packs, then open the Sources tab.
Fill in the source details:
| Field | Description |
|---|---|
| Name | A human-readable identifier for this source (e.g. acme-pack-repo). Must be unique within your organization. |
| Type | Git or OCI. |
| URL | For Git: the HTTPS clone URL of your repository. For OCI: the registry reference (e.g. ghcr.io/acme/scrydon-catalog). |
| Ref | Git branch/tag (default: main) or OCI tag (default: catalog). |
| Catalog path | Path to scrydon.yaml inside the source (default: scrydon.yaml). |
| Access credential | Optional. For a private source, paste the credential directly (Git PAT, deploy-key PEM, or OCI username:token). It's saved as an encrypted organization secret and referenced automatically. Leave blank for public sources. See Authenticating a private source. |
| Signature policy | See Signature Policies below. |
| Sync interval | How often the reconciler checks for changes (30 seconds–1 day). |
Click Test connection to verify the reconciler can reach your source and parse scrydon.yaml without persisting anything.
The source is enabled immediately. The first sync runs within one interval.
For installations managed with Helm, pack sources can also be seeded via packSources: in your chart values file. Helm-managed sources appear read-only in the UI with a "managed by chart" banner. See the Helm reference for the full schema.
Authenticating a private source
Private Git repositories and private OCI registries need a credential. Paste it straight into the source's Access credential field — Scrydon saves it as an encrypted organization secret for you and wires up the reference automatically. You never manage a separate secret by hand.
In Access credential, enter:
- Git over HTTPS — a personal access token (PAT) with
readscope on the repository. - Git over SSH — a deploy-key private key in PEM form (begins with
-----BEGIN). - OCI — a
username:tokenpair for the registry.
Click Test connection — it uses the credential you just entered (before anything is persisted), so a green result confirms it works. On Save, the credential is stored as an encrypted org secret (named pack-source-<name>) and the source references it; every sync resolves and decrypts it automatically.
To rotate, edit the source and enter a new value (leaving it blank keeps the current one). Saved credentials are never displayed again. The underlying secret is visible (and manageable) under Settings → Secrets.
Credentials are stored as organization-scoped secrets in Scrydon (LOCAL strategy). External-KMS-backed secrets (BYOK/HYOK) aren't used for pack sources yet — a source falls back to anonymous access if its credential is external or missing.
Delivering custom integrations
A pack can include an integration content entry in its pack.json. When such a pack is installed, the platform registers the custom integration alongside any other content kinds (ontology, process-flow, etc.) — no separate upload step.
Sync only places packs in your org catalog — installation is an explicit second step. The Settings → Platform → Integrations → Add Integration marketplace is where custom integrations are discovered and first installed. The Settings → Platform → Packs → Catalog tab is where you track install state across all content kinds and apply updates.
In the marketplace, synced custom integrations appear under From your pack catalog:
- Not yet installed — shows an Add button; clicking it installs and activates the integration immediately.
- Already installed and current — shows an Up to date indicator and remains in the pack catalog group. Clicking the card opens the vendor configuration view.
- Update available — shows an Update badge. Clicking the action deep-links to Settings → Platform → Packs so you can review workflow impact and apply the update there. See Pack version management.
Installing a whole pack (including its non-integration content kinds such as ontology, workflows, and data sources) is done via the Install row action under Settings → Platform → Packs → Catalog.
Adding an integration from the marketplace activates it immediately — the explicit admin action is the review. Signature policy gates non-interactive flows:
| Install trigger | Activation status |
|---|---|
| Explicit admin install (marketplace Add/Update, catalog Install) | Active |
Non-interactive install, cosign-keyless / cosign-key source | Active |
| Non-interactive install, unsigned artifact | Pending Review — approve under Integrations → Custom |
Pack size limit for integration artifacts: 8 MB per bundle.tar.gz. Larger integrations must use the Manual upload door (50 MB). See the pack authoring guide for the full subdir layout and pack.json declaration.
Signature Policies
Every pack artifact must pass signature verification before it is installed. The signature policy is set per source at registration time.
| Policy | Use case |
|---|---|
cosign-keyless | Artifacts signed via GitHub Actions OIDC (no key management required). Specify certificateIdentityRegexp to pin to a specific repository and certificateOidcIssuer to pin to the OIDC provider. |
cosign-key | Artifacts signed with a static key pair. Provide the PEM-encoded public key. |
unsigned-allowed | Explicit opt-in to skip signature checks. Not recommended for production. Surfaces a permanent warning banner in the UI. |
cosign-keyless (recommended)
signature:
kind: cosign-keyless
certificateIdentityRegexp: "https://github.com/acme/scrydon-packs/.*"
certificateOidcIssuer: "https://token.actions.githubusercontent.com"The reconciler calls cosign verify with these constraints. The OIDC issuer and certificate identity must match exactly — a pack signed in a different repository or by a different CI system will fail verification.
For this to work, your publish workflow must request id-token: write permission and use sigstore/cosign-installer@v3.
cosign-key
signature:
kind: cosign-key
publicKey: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----Generate a key pair with cosign generate-key-pair and paste the public key above. Keep the private key in a CI secret (COSIGN_PRIVATE_KEY) and sign with cosign sign --key env://COSIGN_PRIVATE_KEY.
unsigned-allowed
Use only for local development or air-gapped lab environments where running a signing infrastructure is impractical. In scrydon.yaml, entries under a unsigned-allowed source use signature: { kind: none }.
unsigned-allowed is logged as a security event at registration time. Every sync run under this policy is also flagged in the audit log. Enable it for a production source only after explicit acceptance by your security team.
Troubleshooting
verify_failed
Signature verification failed for one or more pack artifacts.
- Check that your publish workflow has
id-token: writepermission (for keyless). - Confirm the
certificateIdentityRegexpmatches the GitHub Actions run URL for your repository (e.g.https://github.com/acme/scrydon-packs/.*). - Confirm the
certificateOidcIssuermatches the OIDC provider your CI uses (https://token.actions.githubusercontent.comfor GitHub Actions). - For
cosign-key: verify the public key in the source configuration matches the private key used to sign the artifact. - Check that the pack was signed after being pushed to the registry — signing a different tag or digest than the one referenced in
scrydon.yamlwill fail.
fetch_failed
The reconciler could not reach your source.
- For Git sources: verify the URL is an HTTPS clone URL and that any credentials (PAT or deploy key) have
readscope on the repository. - For OCI sources: verify the registry reference is correct and that the pull credentials have read access to the repository.
- Verify the source is reachable from your Scrydon cluster's network. The reconciler makes outbound HTTPS requests — ensure egress is not blocked.
- Click Test connection in Settings to get a more detailed error.
parse_failed
scrydon.yaml failed schema validation.
- Run the validator locally:
bunx @scrydon/sdk-authoring sources validate scrydon.yaml - Common causes: unknown keys (typos), missing required fields, invalid pack ID format (must be dotted lowercase, e.g.
acme.fraud), invalid semver, artifactrefmissing for OCI entries. - Confirm the file is valid YAML before checking the schema.
install_failed
The pack was fetched and verified but failed to install.
- The pack bundle itself may be malformed. Test it locally:
bunx @scrydon/sdk-authoring pack test packs/fraud - Check the run history error detail in Settings > Platform > Packs > Sources tab — click a source row (or its View history action) to open the run-history panel — for the specific
pack.jsonvalidation error. - Confirm the
pack.jsonpackage.idmatches the dotted-lowercase pattern and thatinstallOrdermatches the kinds incontents.
Source shows "managed by chart" and is read-only
This source was seeded via packSources: in your Helm values. Edit the chart values to change it — do not create a duplicate UI-managed source with the same name.
Sync stops after repeated failures
After three consecutive failed runs, the reconciler backs off to double the configured interval (capped at one hour). Fix the underlying error — the backoff resets automatically on the next successful sync. Clicking Sync now in the UI resets the counter immediately.
A retired pack came back / a pack is missing from the catalog
Source-managed packs follow the source catalog: a retired pack that is still listed in scrydon.yaml is restored on the next sync (see The source catalog wins). Conversely, if a pack you expect is missing, check that it is listed in the source's scrydon.yaml, that the latest run in the source's history succeeded, and that the Sync now toast reports it as installed — then retire/restore state follows the source automatically.