# Daily Upload Filename Provenance

## Status

Implemented, migrated and loaded in the authenticated port-8766 runtime; one no-PII live write-path check remains.

## Problem

The browser submitted the selected XML basename, but `ProgrammaticUploadCoordinator` normalized the source object to
`source.xml` and did not persist the browser value. Daily history and task trace then read
`ingestion.artifacts.original_filename`, exposing the internal canonical artifact name as if it were the uploaded name.

The existing 24 July history rows therefore cannot recover their original client filenames from current database
facts. Guessing from business dates or object names would create false provenance.

## Implemented Boundary

- Added and applied migration `013_daily_upload_filename.sql`.
- Added nullable `ingestion.processing_runs.uploaded_filename` with basename, control-character, length and XML-suffix
  checks.
- The active and legacy upload coordinators pass the already validated browser filename through `JobRegistration`.
- `PostgresIngestionRepository` stores and identity-checks that value when registering a run.
- Daily history and task trace now select `run.uploaded_filename`.
- The frontend renders `—` when historical provenance is absent.
- Source objects, processor input and independent validation continue to use canonical `source.xml`.
- The down migration refuses to discard the column after any upload provenance has been recorded.

## Database Evidence

- Migration SHA-256:
  `f7ea18d6b844d9bd90fa757a4cf8428d1dd5833c088ae23444ac81fbe204fb0a`.
- Down-migration SHA-256:
  `663d287e36bb99533d28918d8ead7a2b03e8bbf7e7d682a527400d11f0ee3fbf`.
- Post-migration state: 25 processing runs, zero non-null uploaded filenames, validated
  `processing_runs_uploaded_filename_check`.
- July repository state: 24 history rows, 24 unknown uploaded filenames, zero internal `source.xml` values exposed by
  the new query.
- A transaction-only probe used synthetic basename `歌剧院-0723.XML`; both history and trace returned that value while
  the source artifact remained `source.xml`. The transaction was rolled back and left no probe data.

## Automated Evidence

- 69 focused migration, programmatic-ingestion, repository, trace, direct-ingestion and Web tests passed.
- JavaScript syntax and changed Python module compilation passed.
- Full discovery passed 312 tests in 99.280 seconds with 10 environment/fixture skips and no failures or errors.

## Runtime Activation Boundary

The former 17:13 process predated both this change and application login. It later exited, and the replacement runtime
now starts with Keychain-backed Web/OSS credentials, reports all five readiness flags true and serves authenticated
`/api/jobs` with the existing total of 24. Activation intentionally submitted no XML, so one controlled no-PII upload
must still verify that a new browser basename appears in live history/trace while the internal artifact remains
`source.xml`.
