# An ALLOWLIST: ignore everything, then name what a build is allowed to see.
#
# Round 624 found this file deciding, silently, that two images could not be
# built. It is the right shape — a denylist would ship `vendor/`, `tests/` and
# `runtime/` into production the first time somebody forgot a line — but it has
# a failure mode nothing was watching: **a COPY naming a path this file does not
# admit does not degrade, it fails the whole image**, and nothing in CI builds
# one. `DockerBuildContextTest` now checks every COPY in `docker/Dockerfile`
# against these rules, and refuses an exception that matches nothing.

# Ignore everything
*

# except:

# The edge config. Both stages need one: `docker/Caddyfile` for prod,
# `docker/dev/Caddyfile` for dev and test.
!/docker/**/Caddyfile

# The PHP settings (round 615, INV-044). ADDED IN ROUND 624, and its absence is
# the finding: `base` has copied this file since round 615, `*` excluded it, and
# `!/docker/**/Caddyfile` re-includes Caddyfiles under `docker/` and nothing
# else — so every image build, dev and test included, has failed since that
# round. `UploadLimitChainTest` stayed green throughout because it asserts the
# COPY LINE exists, and a line is not a file.
!/docker/php/app.ini

# The application.
!/config
!/public
!/src

# ADDED IN ROUND 805, the first time the image's own file set was served
# (behind a TLS proxy, on MySQL, every GET route requested): both are read at
# run time through aliases in config/common/aliases.php, and without them 32 of
# the 81 routes answered 500 — the home page, sign-in and every public
# one-time-link page among them.
# - the shared view components (`@components`);
!/templates
# - the stylesheets the layout publishes (`@assetsSource`, MainAsset).
!/assets

# What the asset manager has published on the machine doing the build is not
# part of the application: a stale copy baked into an image would be served in
# place of the current stylesheet. The directory itself stays (it is where the
# running application publishes), kept by its .gitignore.
/public/assets/*
!/public/assets/.gitignore

# The schema. ADDED IN ROUND 624. Without it a production image has no
# migrations at all, and `./yii migrate:up` reports success over an empty set —
# INV-047's defect one layer out: not a migration in the wrong directory, but
# the right directory left out of the image. CLAUDE.md's own hard rule is
# "migrations only — zero manual DDL", which an image without them cannot keep.
!/migrations

# ADDED IN ROUND 948: the release carries the files that deploy it. A node
# releasing a tag takes these three out of the image it is about to run
# (infra/terraform/modules/environment/node-release.sh), so what deploys a
# release is what was built, scanned and pushed with it — never a copy from
# somewhere else. They hold no secret: the settings and the secrets stay on the
# swarm.
!/bin/prod-deploy.sh
!/docker/compose.yml
!/docker/prod/compose.yml

# ADDED IN ROUND 952: the production image's start, which makes the
# container's own TLS key (Cham's Q148 (1)). A script, no secret.
!/docker/prod/serve.sh

# Round 1016 (ASVS V12.3.1): the certificate authorities that sign the
# London RDS database's certificate. The connection is refused unless the
# database proves itself with one of them.
!/docker/prod/rds-eu-west-2-bundle.pem

!/yii
!/composer.json
!/composer.lock

# `!/.env*` was here until round 948, and it admitted `.env` itself: an image
# built on a machine with a local `.env` carried that file, and whatever
# credentials were in it, into the registry. Production never reads one
# (phpdotenv is a dev dependency, and settings arrive from the swarm), so no
# `.env` file of any kind goes into an image.

# `!autoload.php` was here until round 624 and matched nothing — there is no
# such file. It admitted nothing and still read as a considered decision, which
# is round 559's finding in the one file where a wrong entry means an image that
# does not build.
#
# `runtime/` is deliberately absent: nothing writes there. The logger is a
# StreamTarget (stderr) and `@runtime` has no other consumer in `src/` or
# `config/`. Dev gets one as a bind mount; production needs none until something
# actually asks for it, and baking an empty directory in to be safe would be a
# guess about a need nobody has demonstrated.
