# Operations reference

Run commands from the repository root. Replace `<APP>` with an ID from ` node scripts/ci/catalog.mjs list`.

## Local commands

| Command                                         | Result                                                               | Remote mutation                       |
| ----------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------- |
| make app-create APP=<APP> DESCRIPTION="Purpose" | Source, Terraform declaration, catalog entry, README row             | None                                  |
| make app-setup APP=<APP>                        | Frozen shared and app dependency installation                        | None; may download dependencies       |
| make app-dev APP=<APP>                          | App development server; app and gateway use the existing local stack | Inspect app-specific dev behavior     |
| make app-types APP=<APP>                        | Ignored binding declarations for a root Wrangler config              | None                                  |
| make app-verify APP=<APP>                       | App verification and build/dry-run contract                          | No production deployment              |
| make app-package APP=<APP>                      | Package an already verified build under .release/                    | None                                  |
| make app-release-check APP=<APP>                | Dry-run the package                                                  | None                                  |
| make fmt                                        | Terraform formatting                                                 | None                                  |
| make verify                                     | Repository, agent, catalog, CI, and Terraform checks                 | No apply; backend-free initialization |
| node scripts/ci/catalog.mjs check               | Catalog, dependency graph, and README inventory validation           | None                                  |
| node scripts/ci/select.mjs <BASE> <HEAD>        | Changed-path root, verification, and deployment selections           | None                                  |

Custom configuration generators need their app-specific type-generation procedure. App and gateway development use `scripts/apps/dev/`; the catalog's ` localStack` flag alone does not supply new configuration/build specifications.

## Catalog fields and discovery

| Field or convention                  | Meaning                                                               |
| ------------------------------------ | --------------------------------------------------------------------- |
| version: 1                           | Catalog schema version                                                |
| apps.<APP>.purpose                   | Human-readable application purpose                                    |
| org/apps/<APP>/                      | Conventional source directory                                         |
| org/cloudflare/app-<APP>.tf          | Conventional Terraform owner                                          |
| Root wrangler.jsonc or wrangler.json | Default release configuration; at most one                            |
| runtimeDependencies                  | Exceptional runtime dependencies not inferred from root config        |
| buildDependencies                    | Exceptional bundled dependencies not inferred from package references |
| localStack                           | Whether the existing shared local stack prepares the app              |
| deployLast                           | Final deployment-stage selection, used by gateway                     |
| scripts/apps/adapters/<APP>.mjs      | Custom configuration/preparation for a nonstandard build              |
| scripts/apps/smoke/<APP>.sh          | Optional app-specific post-deployment behavior check                  |

The loader infers ordinary dependencies; do not duplicate them in catalog metadata. The catalog validates source registration, not live inventory. Its current deployment graph must be acyclic. The workflow has three ordinary stages, numbered `0` through ` 2`, and a final stage ` 3` for ` deployLast` apps. A longer dependency chain requires a reviewed workflow change; it does not create additional stages automatically.

## Toolchain ownership

Plain Workers resolve Wrangler, TypeScript, and tests from the root manifest and lockfile. Data and gateway use this arrangement. Framework and vendored apps can have isolated manifests and lockfiles. `scripts/apps/pnpm.sh` selects that package owner before invoking pnpm.

The root `config.workerCompatibilityDate` seeds newly created Workers. An existing app's Wrangler compatibility date remains an explicit runtime choice. Updating the toolchain does not automatically change that date.

## Release and version identifiers

| Identifier                             | Meaning                                                                |
| -------------------------------------- | ---------------------------------------------------------------------- |
| Git commit SHA                         | Reviewed source and the workflow's selected revision                   |
| Package manifest revision              | Commit associated with a packaged app                                  |
| Package manifest files                 | SHA-256 checksums for packaged files                                   |
| Manifest SHA-256 in deployment summary | Identifies the manifest used by the deployment                         |
| Wrangler deployment receipts           | Cloudflare's Worker deployment/version identifiers emitted by the tool |
| pnpm and dependency versions           | Build-tool inputs recorded in manifests and lockfiles                  |
| Worker compatibility date              | Cloudflare runtime compatibility behavior                              |
| Immutable asset directory version      | Public URL contract; independent of package or Worker version          |

A monorepo commit can deploy only a subset of apps. Use per-app receipts to identify what actually changed. Package versions and compatibility dates are not substitutes for release evidence.

## Artifacts and retention

| Artifact             | GitHub Actions name                   | Retention |
| -------------------- | ------------------------------------- | --------- |
| Verified app package | app-<APP>-<SHA>                       | 7 days    |
| Deployment receipts  | deployment-<APP>-<SHA>-<RUN\_ATTEMPT> | 30 days   |

Packages contain compiled modules, assets, owned migrations, configuration, and a manifest. Deployment overlays production settings on `.release-deploy/` and removes that working copy afterward. Downloaded artifacts and their metadata remain operational evidence; checksums detect changes but are not an independent signing or approval mechanism.

For a Worker with multiple D1 bindings, only bindings with an explicit `migrations_dir` own migrations. A consumer binding must omit that field. A Worker with one D1 binding can use the default ` migrations/` directory when it exists. Deployment applies only the migrations listed in the package manifest.

## Canonical implementation

- [Catalog and selection](https://github.com/StormTrust/infrastructure/tree/main/scripts/ci)
- [Shared app tooling](https://github.com/StormTrust/infrastructure/tree/main/scripts/apps)
- [Main release workflow](https://github.com/StormTrust/infrastructure/blob/main/.github/workflows/apply.yml)
- [App deployment workflow](https://github.com/StormTrust/infrastructure/blob/main/.github/workflows/deploy-app.yml)
- [Application declarations](https://github.com/StormTrust/infrastructure/tree/main/org/cloudflare)
