Skip to content

Commit af83296

Browse files
authored
Fix filtered portable archive trust metadata (#5065)
* Fix filtered archive trust metadata (#5053) * Harden legacy archive trust import (#5053) * Preserve partial archive trust on scoped updates (#5053) * Release archive test database before hashing (#5053)
1 parent fd3c303 commit af83296

15 files changed

Lines changed: 799 additions & 45 deletions

DEVELOPER_GUIDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ Development contracts:
5656
| Binary compatibility | [COMPATIBILITY.md](COMPATIBILITY.md) | Database compatibility across `cdidx` binary upgrades and downgrades is documented there. Keep that policy updated whenever readiness bits, `codeindex_meta` contract stamps, or rebuild requirements change. |
5757
| Fold backfill preview and recovery | `backfill-fold --dry-run`; `backfill-fold --checkpoint`; MCP `backfill_fold` with `dry_run: true` or `force: true` | Dry-run previews folded-key rows without mutating the DB or stamping FoldReady. `--checkpoint` explicitly preserves a snapshot even when CLI preflight finds no mutation, while the default completed no-op leaves no checkpoint artifacts. MCP accepts the same preview and can force rewriting all folded keys when an operator needs to recover from suspicious fold metadata or row state even though the stored version/fingerprint appears current. Non-dry-run row rewrites are resumable after interruption: completed row updates remain durable, and final FoldReady metadata is stamped only after verification succeeds. MCP responses include `progress.rows_done`, `progress.rows_total`, and `progress.fraction` so clients can report and retry long backfills. |
5858

59+
Portable archive trust is scope-aware. Unfiltered exports set `scope.represents_entire_source_database` and preserve completeness, indexed-HEAD, run, and unknown-extension metadata. Filtered exports normalize only the archive snapshot to `index_complete=false` with `partial_archive`, remove source-wide HEAD/run provenance, and omit unavailable unknown-extension summaries. Import repeats that normalization for legacy manifests without scope metadata, while current full-snapshot manifests preserve trust. Scoped indexing of a partial archive falls back to a full workspace scan before it may clear `partial_archive`.
60+
5961
Checkpoint plan drift detection covers DB/WAL/SHM content changes and sidecar appearance or disappearance through the final pre-publication validation. The plan's `uncertainty` value records the remaining post-validation race; copied outputs are independently hash-verified against the plan before atomic publication. DB/WAL/SHM candidates must pass native regular-file type validation before hashing so Unix FIFOs cannot block planning. `metadata_policy` reports `owner_only_files_and_directories` on POSIX and the actually inherited `inherited_windows_acls` policy on Windows. A database payload whose output name collides with `manifest.txt`, including filesystem-equivalent casing, makes the plan not ready and is rejected before mutation.
6062

6163
## Filesystem Permissions
@@ -3719,6 +3721,8 @@ net9 CI lane に合わせる場合は `FRAMEWORK=net9.0 make test` を使いま
37193721
| binary compatibility | [COMPATIBILITY.md](COMPATIBILITY.md) | `cdidx` binary の upgrade / downgrade をまたぐ database compatibility を記載します。readiness bit、`codeindex_meta` contract stamp、rebuild requirement を変える場合は、この policy も更新してください。 |
37203722
| Fold backfill の preview / recovery | `backfill-fold --dry-run`; `backfill-fold --checkpoint`; MCP `backfill_fold` の `dry_run: true` または `force: true` | dry-run は DB を変更せず FoldReady stamp も書かずに、rewrite 対象の folded-key row をプレビューします。CLI preflight でmutation不要と判断された場合でもsnapshotを明示的に保存するには `--checkpoint` を使います。既定の完了済みno-opはcheckpoint artifactを作りません。MCP も同じ preview を受け付け、stored version / fingerprint が current に見える場合でも suspicious な fold metadata や row state を復旧するため `force: true` を受け付けます。non-dry-run rewrite は中断後に resume でき、完了済み row update は durable に残り、最終 FoldReady metadata は verification 成功後にだけ stamp されます。MCP response は `progress.rows_done`、`progress.rows_total`、`progress.fraction` を含みます。 |
37213723

3724+
portable archive の trust は scope を考慮します。filter なし export は `scope.represents_entire_source_database` を設定し、completeness、indexed-HEAD、run、unknown-extension metadata を維持します。filter 済み export は archive snapshot だけを `index_complete=false` / `partial_archive` に正規化し、source 全体に対する HEAD / run provenance を削除して、未計測の unknown-extension summary を省略します。scope metadata がない legacy manifest は import 時に同じ正規化を行い、現行の full-snapshot manifest は trust を維持します。partial archive に対する scoped index は `partial_archive` を解除する前に full workspace scan へ fallback します。
3725+
37223726
checkpoint plan の drift 検出は、publish 前の最終検証までに起きる DB/WAL/SHM content の変更と sidecar の出現・消失を対象にします。plan の `uncertainty` 値は最終検証後に残る race を記録し、copy 済み output は atomic publish 前に plan の hash と個別に照合されます。DB/WAL/SHM 候補は hash 読み取り前に native regular-file type validation を通すため、Unix FIFO が plan 作成を停止させることはありません。`metadata_policy` は POSIX では `owner_only_files_and_directories`、Windows では実際に継承される `inherited_windows_acls` policy を報告します。database payload の output 名が filesystem 上で同一の大小文字を含め `manifest.txt` と衝突する場合、plan は not ready となり、変更前に拒否されます。
37233727

37243728
## ファイルシステム権限

TESTING_GUIDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ Use `docs/test-doc-maintenance-plan.md` before moving oversized suites or adding
226226
Inspect graph-section coverage must compare name and path/line resolution through the same persisted candidate ID, keep ambiguous overload and partial-family bundles isolated, assert independent total/returned/truncated metadata for references, callers, and callees (including empty sections), and replay a query-, page-size-, and generation-bound cursor across the smallest two-row page boundary. Put inbound callers in another file to prove the location path is only a locator, seed equal-rank same-line callees to pin the complete identity tie-breakers, reject page-size changes before candidate lookup, reject inspect cursors in another command, and verify the same envelopes in MCP `analyze_symbol`.
227227
Quiet-flag coverage in `ProgramCliTests.cs` reuses one seeded symbols database across text, NDJSON, and JSON-array modes and compares stdout with and without a trailing quiet alias, proving that quiet mode changes only informational stderr.
228228
Archive-import validation coverage reuses one pristine database export across read-only dry-run and check modes with distinct destinations. Rejection coverage copies one pristine export into manifest-count, database-hash, and user-version variants before mutating any ZIP so one corruption cannot contaminate another.
229-
Archive success-path coverage seeds one metadata-rich database and shares its pristine export across scoped manifest inspection, a default import into a nonexistent destination, a copied legacy-manifest import, and a separate `--no-backup` replacement. Keep the default import and replacement as distinct CLI calls and destinations, and never mutate the pristine archive.
229+
Archive success-path coverage seeds one metadata-rich database and shares its pristine export across scoped manifest inspection, a default import into a nonexistent destination, a copied legacy-manifest import, and a separate `--no-backup` replacement. Scope coverage must prove a filtered snapshot is incomplete with `partial_archive`, has no source-wide HEAD/run trust, omits unavailable unknown-extension coverage, fails `status --check`, and leaves the source DB unchanged. A later scoped index must fall back to a full workspace scan before restoring complete trust. Full-import coverage preserves those trust fields, while the copied scope-less manifest materializes the same conservative partial state. Keep the default import and replacement as distinct CLI calls and destinations, and never mutate the pristine archive.
230230
Doctor full-inventory coverage keeps composed filter selection, filtered summary counts, exact UTF-8 byte-budget boundaries, and structured overflow errors together in `ProgramRunnerTests`; license JSON remains a subprocess contract in `ProgramCliTests` so immediate-command dispatch and the published field names are both exercised.
231231
Ctags export JSON coverage reuses one seeded database for default and `--include-generated` variants, asserts the fixed skip-reason keys sum to `skipped_count`, and keeps the missing-`files.generated` degradation in a separate legacy-schema fixture.
232232
Dry-run JSON coverage for ambiguous `.h` files locks the bounded `language_detections` entries and their stable source/confidence codes without mutating the index.
@@ -1226,7 +1226,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"
12261226
inspect graph-section coverage では、name と path/line resolution が同じ persisted candidate ID を通ること、曖昧な overload と partial-family bundle が分離されること、references / callers / callees の独立した total / returned / truncated metadata(空 section を含む)を検証してください。inbound caller は別ファイルに置いて location path が locator にすぎないことを証明し、最小の2行 page 境界で query / page size / generation に束縛された cursor を再利用します。同順位かつ同じ行の callee で完全な identity tie-breaker を固定し、candidate lookup より前に page-size 変更を拒否し、別 command では inspect cursor を拒否してください。MCP `analyze_symbol` でも同じ envelope を確認します。
12271227
`ProgramCliTests.cs` の quiet flag coverage は1つの seeded symbols database を text、NDJSON、JSON array の各 mode で再利用し、末尾に quiet alias を付けた場合と付けない場合の stdout を比較して、quiet mode が informational stderr だけを変えることを固定します。
12281228
archive import validation coverage は、read-only な dry-run / check mode で1つの pristine database export を別々の destination から共有してください。拒否 coverage では、mutation 前に1つの pristine export を manifest-count、database-hash、user-version 用の3つの ZIP へコピーし、ある corruption が別 case を汚染しないようにします。
1229-
archive success-path coverage は、metadata-rich な database を1回 seed し、その pristine export を scoped manifest inspection、存在しない destination への default import、コピーした legacy manifest の import、別 destination への `--no-backup` replacement で共有します。default import と replacement は別々の CLI 呼び出しと destination に保ち、pristine archive を直接変更しないでください。
1229+
archive success-path coverage は、metadata-rich な database を1回 seed し、その pristine export を scoped manifest inspection、存在しない destination への default import、コピーした legacy manifest の import、別 destination への `--no-backup` replacement で共有します。scope coverage では filter 済み snapshot が `partial_archive` により incomplete となり、source 全体に対する HEAD / run trust を持たず、未計測の unknown-extension coverage を省略し、`status --check` が失敗し、source DB が変更されないことを検証してください。後続の scoped index は complete trust を復元する前に full workspace scan へ fallback しなければなりません。full import はそれらの trust field を維持し、scope を除いた manifest のコピーは同じ保守的な partial state を materialize します。default import と replacement は別々の CLI 呼び出しと destination に保ち、pristine archive を直接変更しないでください。
12301230
doctor full-inventory coverage では、合成 filter の選択、filtered summary 件数、UTF-8 byte budget の exact boundary、structured overflow error を `ProgramRunnerTests` にまとめます。license JSON は `ProgramCliTests` の subprocess contract として、immediate-command dispatch と公開 field 名を同時に検証します。
12311231
ctags export JSON coverage は1つの seeded database を既定と `--include-generated` variant で再利用し、固定された skip-reason key の合計が `skipped_count` と一致することを検証します。`files.generated` がない場合の縮退は別の legacy-schema fixture に保ってください。
12321232
曖昧な `.h` に対する dry-run JSON coverage は、index を変更せず、上限付き `language_detections` entry と安定した判定元・信頼度 code を固定します。

USER_GUIDE.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,17 @@ exclusion, and test filters then narrow that scope. The exported SQLite
505505
snapshot contains only the retained files and their dependent chunks, symbols,
506506
references, and diagnostics, and is vacuumed before packaging. JSON output and
507507
`manifest.json` include the requested scope, resolved project paths, and source
508-
and exported file counts. An export without scope flags remains a full archive.
508+
and exported file counts. The scope also reports
509+
`represents_entire_source_database`. An export without scope flags remains a
510+
full archive and preserves the source database's index completeness,
511+
indexed-HEAD provenance, run telemetry, and unknown-extension summary. A
512+
filtered archive is instead stamped `index_complete: false` with the stable
513+
`partial_archive` reason, clears source-wide indexed-HEAD and run metadata, and
514+
omits unavailable unknown-extension summaries so `status` cannot present the
515+
subset as a fresh full index or an authoritative zero-result scan. This
516+
normalization applies only to the exported snapshot and does not mutate the
517+
source database. A later scoped index request falls back to a full workspace
518+
scan before clearing `partial_archive`.
509519
Portable export refuses an existing destination by default; pass `--overwrite`
510520
only when replacing it is intentional. The archive is built in an owner-only
511521
sibling temporary file and atomically published, and POSIX archives are verified
@@ -521,8 +531,11 @@ database. `--prune-paths` rewrites the imported `indexed_project_root` metadata
521531
to the import target project root. Imports targeting `.../.cdidx/codeindex.db`
522532
use the sibling project directory; other database paths fall back to the process
523533
current directory. `--dry-run` and its `--check` alias also compare an existing
524-
destination DB with the validated archive without replacing it. JSON
525-
`destination_delta.comparison` reports schema and count deltas plus bounded
534+
destination DB with the validated archive without replacing it. JSON results
535+
expose the normalized `index_complete`, `index_incomplete_reasons`, and `scope`
536+
values. Archives with no scope metadata are treated conservatively as partial
537+
during import; current unfiltered archives explicitly preserve full-snapshot
538+
trust. JSON `destination_delta.comparison` reports schema and count deltas plus bounded
526539
file, symbol, reference-edge, chunk, and metadata records. Text fields in those
527540
records are represented by named SHA-256 and UTF-8 byte-length metadata rather
528541
than source content or paths. Use `--limit <n<=10000>` and `--offset <n>` to
@@ -3999,7 +4012,15 @@ archive export では `--lang`、繰り返し指定できる `--path` / `--exclu
39994012
さらに絞り込みます。出力する SQLite snapshot には残した file と、それに従属する
40004013
chunk、symbol、reference、diagnostic だけを保持し、packaging 前に vacuum します。
40014014
JSON output と `manifest.json` には指定 scope、解決済み project path、元と出力後の
4002-
file count が含まれます。scope flag を指定しなければ従来どおり full archive です。
4015+
file count が含まれます。scope には `represents_entire_source_database` も含まれます。
4016+
scope flag を指定しない full archive は source database の index completeness、
4017+
indexed-HEAD provenance、run telemetry、unknown-extension summary を維持します。一方、
4018+
filter 済み archive は `index_complete: false` と stable reason `partial_archive` を記録し、
4019+
source 全体に対する indexed-HEAD / run metadata を消去し、未計測の unknown-extension
4020+
summary を省略するため、`status` が subset を fresh な full index や authoritative な
4021+
0 件 scan として表示することはありません。この正規化は export snapshot だけに適用され、
4022+
source database は変更しません。後続の scoped index request は `partial_archive` を解除する前に
4023+
full workspace scan へ fallback します。
40034024
portable export は既存 destination を既定で拒否します。意図して置き換える場合だけ
40044025
`--overwrite` を指定してください。archive は owner-only の sibling temporary file に
40054026
構築して atomic に publish し、POSIX では mode `0600` であることも検証します。
@@ -4014,7 +4035,10 @@ SQLite file が CodeIndex DB であることを検証してから destination da
40144035
`.../.cdidx/codeindex.db` を import 先にした場合は sibling の project directory を使い、
40154036
それ以外の database path では process current directory に fallback します。
40164037
`--dry-run` と alias の `--check` は置換せず、既存 destination DB と検証済み archive を
4017-
比較します。JSON の `destination_delta.comparison` には schema / count delta と、
4038+
比較します。JSON result は正規化後の `index_complete`、`index_incomplete_reasons`、
4039+
`scope` を公開します。scope metadata がない archive は import 時に保守的に partial と
4040+
扱い、現行の filter なし archive だけが full snapshot の trust を明示的に維持します。
4041+
JSON の `destination_delta.comparison` には schema / count delta と、
40184042
file、symbol、reference edge、chunk、metadata の bounded record が含まれます。
40194043
これらの record の text field は source content や path そのものではなく、名前付きの
40204044
SHA-256 と UTF-8 byte length metadata として表現されます。record の paging には
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
category: fixed
3+
issues:
4+
- 5053
5+
affected:
6+
- src/CodeIndex/Cli/ExportImportCommandRunner.ArchiveScope.cs
7+
- src/CodeIndex/Cli/ExportImportCommandRunner.Manifest.cs
8+
- src/CodeIndex/Cli/ExportImportManifestCodec.cs
9+
- src/CodeIndex/Cli/IndexCommandRunner.cs
10+
- src/CodeIndex/Cli/IndexCommandRunner.Update.cs
11+
- tests/CodeIndex.Tests/ExportImportCommandRunnerTests.cs
12+
- USER_GUIDE.md
13+
- DEVELOPER_GUIDE.md
14+
- TESTING_GUIDE.md
15+
---
16+
17+
## English
18+
19+
- **Filtered portable archives now report conservative trust metadata (#5053)** — Scoped exports and legacy scope-less imports are marked incomplete with `partial_archive`, clear source-wide HEAD/run provenance, omit unavailable unknown-extension summaries, and require a full workspace scan before scoped indexing can restore complete trust, while full unfiltered archives preserve their trust metadata.
20+
21+
## 日本語
22+
23+
- **filter 済み portable archive が保守的な trust metadata を報告するようになりました (#5053)** — scope 付き export と scope 情報がない legacy import は `partial_archive` により incomplete とし、source 全体に対する HEAD / run provenance と未計測の unknown-extension summary を削除します。scoped index が complete trust を復元する前には full workspace scan を必須とし、filter なしの full archive は従来の trust metadata を維持します。

0 commit comments

Comments
 (0)