Context: operators and reviewers moving existing walgit repositories to the packfile design. This document describes a phased review and rollout plan. The bundle-removal review unit does not establish production packfile delivery, protected-client acceleration, or scale performance. Each later unit needs its own tests and compatibility decision before enablement.
- Remove bundle runtime: crate/command, protocol command, list/catch-up routes, schedules, attempt caches, configuration, recipes and UI. Keep ordinary dynamic clone/fetch and durable format decoders.
- Add independent group/discovery policy, exact coverage snapshots/certificates, append-only schema fields, live/retired membership and CAS guards. Prove old-data replay before emitting URLs.
- Add conserving classification/folds/freezes/re-segmentation, repairable proofs, isolated producers, resumable plan/step/seal, memory bounds and verified MIDX bitmap construction.
- Wire request selection, safe engine dispatch/splice, authenticated static serving and retired URL survival.
- Validate distributable clients, supported backend/edge combinations, complete UI/SDK/operator integration, and publish representative correctness/performance receipts and the concrete rollback floor.
Each review unit must build and preserve supported ordinary Git behavior. Stack position is not permission to leave a half-proved URI path enabled. Actual commits, test results and remaining gates belong in the PRs; this plan is not a test receipt.
Remove [bundles] and every [[bundles.strategy]] table, server.roles entries named bundle, and
cache.bundle_list_entries. The new parser rejects these removed host shapes. Environment override loaders
that warn and ignore unknown keys are not migration tools: remove corresponding WALGIT__BUNDLES__* and
cache overrides from the host's deployment configuration as well.
The lifecycle layer replaces [compaction] with [packs]; old host keys and newly submitted old settings
are rejected. The ordinary compact role remains. LFS serve_via = "proxy" or "signed_url" is unchanged.
Use the documented lifecycle fields in walgit.example.toml: factor/count/age triggers, settlement freeze,
ratio-driven re-segmentation, and bounded delta-search resources. There is no engine selector (Git performs
packing), flat trigger_bytes, or retention_superseded knob. Remove corresponding old environment overrides.
Use walgit config check with the actual host configuration/environment before restart. Compare rendered
effective placement, auth, maintenance and upstream settings to the intended values.
Existing RepoSettings.toml is durable WAL data. Rejecting new [bundles] input must not erase that record or
make log/checkpoint replay undecodable. It must also not silently discard unrelated overrides or widen ref
visibility/object scope by falling back to broad host defaults.
Before replacing old readers/writers, inspect each repository's saved settings and save its full document, revision and effective configuration. Using the existing administrative settings API/CLI, publish a reviewed replacement document that removes only bundle-specific sections while preserving maintenance, upstream and all other still-supported intent. For example:
# Before: stored by the bundle-serving release.
[bundles]
main_only = true
[maintenance]
checkpoints = false
[upstream]
follow = ["refs/heads/main"]The replacement retains both [maintenance] and [upstream] exactly. The old bundle main_only policy is
not a ref-advertisement policy or an exact future packing certificate. When introducing groups, choose its
replacement deliberately from the saved intent; never reinterpret absence as permission to deliver every
namespace. Preview/validate the replacement, publish through the normal SETTINGS transaction, and reread it.
Coordinate concurrent settings writers during this transition; a whole-document replacement must not overwrite
a newer administrator's change.
The removal phase includes a durable-only read transition: it removes the obsolete bundle table from the
in-memory settings document, warns, and applies the remaining supported overrides. Raw saved TOML and WAL
history are preserved. Host files and newly published settings still reject the removed table. This bounded
exception does not turn main_only or bundle ref filters into new group policy. Publishing the reviewed
replacement document remains the explicit durable migration. A warning followed by dropping every override
and using broad host defaults does not meet the gate.
Historical SETTINGS entries stay intact and replayable; no bucket-wide rewriting or log mutation is authorized.
Rollback/replay to a historical settings revision must apply the same transition checks before object work.
The lifecycle layer has a bounded read transition for old durable documents only. It preserves the raw saved record and maps supported intent into the effective config:
| Saved compaction key | Effective packs key |
|---|---|
| enabled | enabled |
| factor | geometric_factor |
| trigger_packs | fold_when_fresh_packs_reach |
| lease_ttl | lease_ttl |
| engine = "git" | removed; native Git is the only producer |
Old flat byte triggers do not have the same meaning as proportional fold thresholds. Time-limited retired
pack retention contradicts issued-URL safety. If saved trigger_bytes or retention_superseded is present,
the transition disables pack maintenance and warns until an administrator publishes reviewed [packs]
settings. Ordinary serving remains available. It never guesses a size threshold or starts pruning objects.
A document containing both old [compaction] and new [packs] fails validation rather than overwriting either
one. Mapped fields must pass current validation; unsupported old values require an explicit rewrite. Other
settings, including narrow ref selectors and upstream settings, remain intact. Preview the full replacement,
publish through the settings API/CLI and verify the stored revision and effective values. This is bucket-data
compatibility, not a host-config alias. Historical entries are never rewritten.
Audit the public protobuf numbering before adding descriptors. Keep old bundle message decoders and checkpoint bundle-pointer fields, but stop using them for runtime delivery. Existing unclassified packs remain repository data; they are not static offers until classification and exact current-policy proofs establish eligibility.
All writers that rewrite manifests must preserve exact snapshots and retired membership before those fields
become authority. Stop incompatible readers and push, follow, import, checkpoint and maintenance writers before enabling new
authority. A new format number alone cannot fence old binaries: the pre-migration readers do not validate
Manifest.format_version. A future minimum-reader gate protects only readers that implement it; it cannot
retroactively make deployed old readers safe.
An older binary that drops these fields can invalidate issued URLs or proofs even if it can decode the message.
The coverage-foundation writer uses canonical content-addressed ref snapshots and attempt-specific checkpoint
metadata as soon as it runs; there is no separate snapshot-writing toggle. Complete the incompatible-writer
stop before starting this binary against an existing bucket. Old checkpoint snapshots remain readable through
their committed descriptor; readers must not reconstruct an old snapshot address from sequence alone.
The rollback floor is therefore the earliest tested release preserving the new authority, not simply a binary
that accepts the protobuf. A concrete compatible release hash must be recorded before enabling the new writer;
none is certified by the removal unit.
Test old manifest/log/checkpoint fixtures, current-settings migration and rollback/replay behavior. Exercise CAS retries and concurrent publication so stale plans cannot reintroduce retired members or erase proof descriptors.
New recipes stop writing transfer.bundleURI, fetch.bundleURI, or --bundle-uri. Existing clients may still
have repository-local fetch.bundleURI pointing at removed catch-up routes. Explicitly remove that setting
in affected clones; inspect global/origin-scoped configuration too if an operator previously added it. Do not
silently rewrite users' global Git configuration as part of a server upgrade.
Standard clients retain dynamic fetch/clone. fetch.uriProtocols=https can negotiate standard URI delivery on
the native engine for anonymous-read repositories. Remote/gix serving stays dynamic. Protected URI acceleration requires a distributable, license-reviewed
client with verified authenticated downloads; version strings alone are insufficient. Until that gate passes,
document protected dynamic fallback honestly. Never open protected static routes to anonymous requests.
Normal discovery advertises configured refs.advertise selectors, independently of packing groups. The
default includes heads and tags. A complete v2 mirror or backup must explicitly request all namespaces:
git -c protocol.version=2 clone --mirror --server-option=ref-view=all <url>; subsequent complete fetches
also need --server-option=ref-view=all. This changes discovery, not authorization. Receive-pack continues
to see the complete ref set. A v0 client uses the configured advertisement selectors.
Removing code does not authorize deleting bucket data. Obsolete bundles/ objects and checkpoint .bundle
wrappers can be considered for a separate operator cleanup only after no reader/writer depends on them.
Never delete wal/, manifests, logs, refs snapshots or real checkpoint metadata because a bundle wrapped them.
Retired pack data and exact URI membership records are retained without a timeout/count cap in the new design.
Before release, attach graph-equivalence, metadata-isolation, dependency-race, interrupted-download, auth/range, backend/edge, ordinary-client fallback, and engine-combination results. Include cold/truncated-read recovery, conserving maintenance and responsive-refs tests. Representative benchmarks must state exact byte units and measure server and client work, not just reduced application egress. Unfinished gates remain visible in the PR stack and release notes; the design document itself certifies none of them.