# SFCRM AppRelease packaging

AppRelease packaging is an L1 release operation. It converts one exact
`nexuscrm-app-packs` source revision into one immutable, self-verifying
AppRelease publication. It has no deployment environment and consumes no L2
metadata.

The dedicated workflow is:

```text
.github/workflows/package-sfcrm-apprelease.yml
```

Its only input is `source`, which accepts `main` or one exact 40-character
commit. `main` is resolved once to an exact commit before packaging. The
workflow rebuilds the AppRelease from `salesforce-crm-standard`, requires it to
match the committed immutable release for that semantic version, verifies the
publisher attestation, and publishes:

```text
ghcr.io/pingcap-inc/nexuscrm-sfcrm-apprelease@sha256:<digest>
```

The selected commit is treated only as L1 data. The reviewed workflow revision
provides the builder, verifier, and OCI Dockerfile, so replaying an older source
does not replace the packaging controller. Dispatch the workflow itself from
`main`; the `source` input selects the L1 content to package.

Unit tests are not a packaging step. A packaging run performs only the release
path itself: build, byte comparison, verification, and publication.

The workflow summary reports this exact installation reference. Re-running the
same source is safe: the publication is content-addressed and the source commit
is embedded in its descriptor and OCI labels.

Run it for current main:

```bash
gh workflow run package-sfcrm-apprelease.yml \
  --repo pingcap-inc/nexuscrm-app-packs \
  --ref main \
  -f source=main
```

For deterministic replay, replace `main` in `source` with the exact commit.
The AppRelease installer consumes the resulting digest together with its own
L2 source selection. Packaging never reads, assembles, or publishes an L2
overlay and never contacts Test1.
