Skip to content

migration: characterize pg-erd Traefik dynamic-config reload before cutover #109

Description

@seonghobae

Live consumer evidence

Protected ContextualWisdomLab/pg-erd-cloud@main remains exact 8dc746920c12988f082e914879d95e13c9693535. Production-style Compose pins traefik:v3.5.4@sha256:4df0a50fcf71b454c0d7ad17675776dc8d37359deae3291895bdaa008c1b9972, starts --providers.file.filename=/etc/traefik/dynamic.yaml with --providers.file.watch=true, and bind-mounts ./deploy/traefik/dynamic.yaml:/etc/traefik/dynamic.yaml:ro as a single read-only file.

Protected history for deploy/traefik/dynamic.yaml contains the 2026-06-20 introduction 28bed7a871c5e7b47249793f7192a8523d404f2c and no later versioned edit through the pinned protected head. Repository search found no checked-in runtime file-edit/update procedure; the documented production operation is full docker compose -f compose.prod.yaml up -d --build. This does not prove out-of-band mutation never occurs, but it provides no positive authority for treating live file reload as a supported product operation.

#5/#6 characterize static Edge Routing and HTTP Policy. #7/#11/#12 compose stable identities into explicit Pingora peer/runtime/Admin Config slices. None proves that removing Traefik's watched file-provider behavior is operationally neutral. This remains an Admin Config / Operability characterization gap, not permission to copy pg-erd product policy into the gateway.

Selected decision boundary

Do not implement generic Pingora dynamic reload merely because watch=true exists.

Exactly one consumer disposition is required before Traefik removal:

A. Runtime reload is not a supported consumer contract

This remains the evidence-favored path pending consumer-owner confirmation.

  • pg-erd-cloud records that route/header/peer changes require controlled deployment/restart rather than live file mutation;
  • migration acceptance proves versioned config validation, startup, readiness, graceful drain, restart and rollback;
  • watch=true is removed only in the consumer-owner migration lane when a release-qualified Pingora artifact is adopted;
  • no generic hot-reload mechanism is added without another proven consumer requirement.

B. Runtime reload is a supported consumer contract

Only after positive black-box evidence, define a versioned Admin Config contract for reusable edge state:

  • validate the complete candidate snapshot before publication;
  • publish one immutable generation atomically to new requests;
  • reject invalid generations without partial active-state corruption;
  • define last-known-good versus fail-closed behavior;
  • bound reload CPU, memory and synchronization;
  • expose low-cardinality generation/reload telemetry without product payloads;
  • preserve request-selected-destination exclusion and stable admitted peers;
  • prove concurrent traffic, invalid update, recovery, graceful drain and rollback;
  • include transition samples in applicable buyer-path p95 ≤20 ms evidence.

Filesystem notifications, polling, explicit generation publication, SIGHUP and controlled redeployment are implementation alternatives only after semantics and threat model are fixed.

Executable characterization contract

Draft #110 is the writer-safe characterization child pinned to pg-erd-cloud@8dc746920c12988f082e914879d95e13c9693535. It does not mutate consumer source/docs/refs/PR state. Its manual workflow remains protected-main-only because workflow_dispatch cannot provide promotion evidence before the workflow definition reaches protected default branch.

The harness distinguishes in-place write from temp-file+rename/replace, characterizes malformed YAML and semantically invalid references under bounded observation windows, preserves causal Traefik logs across recreation, records concurrent /healthz observations, and proves controlled recreation consumes the current host path. Generated X-CWL-Reload-Generation values exist only in the ephemeral characterization checkout and are not consumer or shared gateway API.

Eight evidence-integrity defects have been driven through source-level RED → minimal repair:

  1. 2efce0a5bf63349809ee5c915c00e147f5fa60d2fb315ea666b77985ab591564dcf657967a1dff11: preserve outgoing-container logs before force-recreate and append phase/container snapshots.
  2. 95e2413cbf52b5c9128c51daba4213e383eac0c8a10a76a29bbaa1592c70a813a3e2cd37cf82672a: finalize the sole Traefik-log digest after the final cleanup snapshot so the receipt describes uploaded bytes.
  3. 1f5424d5f600fdc51eaf57f781dd42705053e5ebe784afc2c497f9e828e90d7c8ea8775706a3b82e: replace fixed-delay invalid-input classification with bounded transition windows requiring three consecutive non-baseline observations and explicit observation duration.
  4. bc98ca4bf1d51c2bbb15fc402fc3bbedb973a9bca64808ae79e2f4e39b850559485c846bd6cb3c7c: require a distinct post-invalid-recovery generation so stale recovery state cannot satisfy the predicate.
  5. 9d02664f04a013c18096109cd33b76ce005671d37f99b9ba3547aac137813ac5da284c9d81c8a79b + 9d5516004fcc3cfa6ff4cdcd0a2dbcf94cf6f09b: remove bind-close host-port TOCTOU by delegating ephemeral allocation to Docker and refreshing the active endpoint after recreation.
  6. 40dad92116d50f993792f814ac5459c3074c06efd5b87916243f075ba84b4d96e8e93613146a9711: fail closed when the always-run evidence upload finds no characterization artifacts instead of silently accepting absence.
  7. fb9a57ec881dac26d0f129f786f389811eb26c0500dd41c81274095b1b631b5060a503b01d2ad079: persist pg-erd-traefik-source-identity.txt immediately after exact gateway and consumer checkout verification, before characterization can fail, with both gateway_source_sha and consumer_source_sha; include that marker in the always-run evidence artifact.
  8. f613b8daa8b10099063645c930f90636690508cd → contract refinement dd1aa387cd323577a0e3cf988306f4cc0e77571c → workflow repair 08d43d4d623060781515fd9239af172e433fe933 → contract refinements 60cfb356e018dfc8f1df36687581368e07a61703, b68649dea9b75ec6ad20b391e8a5173ebca8d9f4 → uniqueness repair 2b8bc4ae5ba1be5c508788151e37bc8bad569907: require every evidence member individually, verify the source marker's exact gateway/consumer pair, verify the receipt already carries the same consumer SHA, hash the marker, and append only the missing gateway_source_sha and source_identity_sha256. This closes marker/receipt mix-and-match without duplicate receipt keys. Focused traceability is code-current at 6bbefffeb3780d8ccb2e3e44c36c67b2a6755400.

The eighth repair changes no characterization traffic, consumer source, route/header/peer policy, Traefik provider configuration, restart decision, production Rust, or shared Admin Config semantics. It only makes the evidence set internally attributable and complete-or-RED.

Because #110 remains Draft behind stale #12, current exact 6bbefffeb3780d8ccb2e3e44c36c67b2a6755400 has Supply Chain 35314967059 and CI 35314967074 both completed skipped; all three CI jobs were skipped under Draft admission. These are lifecycle receipts only, not GREEN. Predecessor review credit does not transfer. Fresh current-range review remains required after parent reconciliation.

Docker's current Compose documentation states that when the host port is omitted the container runtime allocates an unassigned host port; docker compose --project-directory preserves the consumer project base for relative build, env, secret and bind-mount paths when the generated characterization file is used. The tracked consumer Compose remains byte-identical and its exact image/provider/bind-mount assertions remain the characterization authority.

Privacy / authority

Only /healthz status and test-only generation markers are sampled. Authorization, Cookie, request bodies, DSNs, application secrets, user/project identity and product payloads are not required evidence. Product route/header/peer decisions remain consumer-owned. Keyverse identity, Wardnet/EgressWeave policy and product authentication/business logic remain outside this gateway boundary.

A GREEN characterization workflow would mean only that the exact consumer behavior was observed with source-bound evidence. It would not by itself select hot reload, close this issue, or authorize a shared implementation.

Dependency / promotion boundary

Current order remains foundation prerequisites -> #5 -> #6 -> #7 -> #11 -> #12 reconciliation/integration -> #110 ordinary/non-force reconciliation -> fresh exact CI/Supply/current-range review -> protected integration -> manual source-bound characterization -> pg-erd-cloud owner disposition -> selected restart or versioned Admin Config acceptance.

The shared-runtime foundation still has separate supplier Security and release/governance roots. Do not source-copy this gap into stale descendants, wire pg-erd-cloud to a mutable branch/PR, self-approve, weaken gates, or claim immutable release/canary/shadow/cutover/Traefik removal from characterization evidence alone. Runtime adoption remains release-qualified shared artifact -> consumer parity -> shadow/canary -> observed rollback -> cutover -> verified Traefik removal.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions