# Catalog and connect an app

Register an app once and give each resource a single owner. A catalog entry describes source intent; it does not prove that a Worker is deployed or healthy.

## Prerequisites

Choose a distinct lowercase app name. Read root `AGENTS.md` and any application instructions. Use the [first Worker tutorial](/stormtrust/engineering/operations/first-worker/) if you have not used the repository tooling.

1. For a new app, run the scaffolder.  
```sh  
make app-create APP=reports DESCRIPTION="Internal reports API"  
```  
For an existing app, edit its existing entry in `org/catalog.json`. Do not create a second entry or state owner for the same Worker.
2. Declare durable resources in `org/cloudflare/app-reports.tf` using the existing ` worker-app` module where its lifecycle fits. Add bindings to the app's Wrangler configuration. Existing API adapters resolve some production identifiers; a new resource type may require additional integration. Do not assume the scaffolder creates storage or secrets.
3. Choose how to reuse functionality. Import code from `org/shared/` when each consumer should bundle its own copy. Use a service binding when another Worker should own the runtime behavior. For example, add this fragment to a consumer's existing configuration:  
```jsonc  
{  
  "services": [  
    { "binding": "DATA_SERVICE", "service": "stormtrust-data" }  
  ]  
}  
```  
```toml  
[[services]]  
binding = "DATA_SERVICE"  
service = "stormtrust-data"  
```  
Generate types with `make app-types APP=reports`. Use the bound service's documented API and enforce authorization in the receiving Worker. A private binding does not replace tenant or record authorization.
4. Check the inferred dependency graph.  
```sh  
node scripts/ci/catalog.mjs check  
node scripts/ci/catalog.mjs order '["data","reports"]'  
```  
Root Wrangler service bindings, external Durable Object bindings, and tail consumers identify runtime dependencies. Local `file:` and ` link:`package references identify bundled app dependencies. Custom generated configurations need explicit catalog dependencies when discovery cannot see their relationships.
5. Decide whether the app needs public ingress. Follow the existing gateway registry and policy for gateway-managed hostnames. The origin owns its Custom Domain; the gateway owns its Worker Route. Ordinary DNS stays in Terraform. A new scaffold remains private until those changes are reviewed.
6. Document the app's purpose, Worker identities, resources, access boundary, health evidence, and recovery constraints under `/stormtrust/apps/`. Add a central smoke check only when it proves a useful runtime contract. Then [validate](/stormtrust/engineering/operations/validate/) and [deploy](/stormtrust/engineering/operations/deploy/) the change.

The catalog does not dynamically extend `make dev`'s complete local stack. That stack has explicit config and build specifications in ` scripts/apps/dev/`. For a new independent Worker, use ` make app-dev APP=reports` and follow [Cloudflare's multiple-Worker development guide](/workers/local-development/multi-workers/) when testing bindings locally.

## Shared dependencies

Plain Workers use the root manifest and lockfile. Framework or vendored apps may retain isolated manifests and build adapters. Use `scripts/apps/pnpm.sh` when invoking an app's package manager so its pin is selected from the right directory. Add shared dependencies at their actual package owner.

Changes under `org/shared/` or ` org/packages/` conservatively select every app. Do not add a module, package, or adapter without a real consumer.
