App Delivery Pack
The App Delivery Pack (@hellmai/lumenflow-packs-app-delivery) defines three jobs any project
runs when it ships an app: build a binary, submit it to a store track, and ship an update. The build
service and the store sit behind a connector, so a self-hosted project and a hosted service run the
same jobs against the same contract.
The jobs
Section titled “The jobs”| Job | Params | Result and refusals |
|---|---|---|
| Build | app_id, tenant_subject, version, platform, profile, source_archive | build_id, status, artifact_url, install_url, cost_usd, cost_basis, fingerprint, runtime_version, reused_build, error_code |
| Submit | app_id, tenant_subject, build_id, track | A track the manifest marks human-only, or does not list, is refused with unsupported_track |
| Update | action (publish or rollback), channel, version, source_archive, approval (plus app and tenant) | Guard codes no_baseline, runtime_mismatch, config_changed, approval_required |
Build status moves queued to running to succeeded, failed or canceled; the last three are
terminal. A succeeded build of the same app and tenant with the same fingerprint, platform and profile
is reused: the result carries reused_build: true and cost_usd: 0.
Connector manifest
Section titled “Connector manifest”Every platform, profile, track, human-only track and channel name is read from the connector’s
ConnectorManifest; none is a literal in the contract. A channel with requires_approval: true makes
a principal approval mandatory for publish and rollback.
What a guard proves
Section titled “What a guard proves”A guard proves compatibility: the candidate runs on the baseline’s runtime and carries the
baseline’s build-affecting configuration. It proves approval: the principal approval reference
resolves, through your host, to a granted record bound to this action, app, tenant, channel and
version. A caller’s assertion alone never satisfies approval_required.
A guard does not prove intent. It cannot tell whether the change is the one anyone meant to ship or whether the approver understood it.
Credentials stay out of params
Section titled “Credentials stay out of params”Params are strict schemas. A key naming a secret, token, key id, bundle id or account id, and a value
shaped like a private key, bearer token, JWT or provider access key, is rejected with
credential_material_rejected. A connector reaches credentials only through the host’s opaque
credential_ref.
Cost basis
Section titled “Cost basis”cost_basis is reported, estimated or usage_based. Prices are read from a PriceConfig you
supply; a missing price is an error, not a default.
Writing and proving a connector
Section titled “Writing and proving a connector”Implement ProviderConnector (validateCredentials, fingerprint, build, submit, publish,
status), publish a manifest, and run runConformance from the /conformance subpath. It drives the
connector through build, reuse, a refused human-only submit, one refusal per update guard code,
publish and rollback. createFakeConnector from /testing is a template.