Skip to content

schema: POST /contexts/{name}/schema/audit and /schema/validate - #398

Merged
t0k0sh1 merged 2 commits into
mainfrom
385-schema-audit-validate
Aug 4, 2026
Merged

schema: POST /contexts/{name}/schema/audit and /schema/validate#398
t0k0sh1 merged 2 commits into
mainfrom
385-schema-audit-validate

Conversation

@t0k0sh1

@t0k0sh1 t0k0sh1 commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds POST /contexts/{name}/schema/audit (judges every live association against the resident schema document) and POST /contexts/{name}/schema/validate (dry-runs a proposed document without persisting it) — S7 of schema: add optional entity types and relation ontology constraints #218's ADR 0009 split, §10.
  • Both share one judgment (schema_audit, src/api/schema.rs) built on the existing schema_issues/SchemaEnv pure check every write entrance already uses (S3, schema: the reserved type label and the shared pre-write check #381), and both judge as strict would regardless of the document's actual mode — per §7.1, pre-existing violations are otherwise invisible in off/warn.
  • Response is DriftAudit-shaped: violations (domain/range, the only paged section), untyped_concepts, undeclared_types (§6.2, always on), unknown_labels (§6.4, only under closed_labels), and reserved_alias_conflicts (§6.3 guard 2, only reachable through validate since PUT /schema already refuses to install over such a conflict). Deprecated-relation usage is out of scope per §9.2.
  • Both routes are Role::Read, join the unconditional heavy-ops group, and have audit_schema/validate_schema MCP tool twins.

Test plan

  • cargo fmt --all --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test (full suite, 2066 tests, 0 failed)
  • New integration suite tests/http_api/schema_audit.rs (11 cases: 404s, mode-independence, all four audit sections, pagination, reserved-alias conflict via validate, invalid-document refusal, non-persistence)
  • Extended key_scopes_cross_context.rs, replication.rs, and mcp_basics.rs for role classification, replica read-through, and MCP round-trip

Closes #385

https://claude.ai/code/session_01FJSVDt6KNgjbjdtJeLxMC9

Summary by CodeRabbit

  • 新機能

    • スキーマ監査APIと、提案スキーマを保存せず検証できるAPIを追加しました。
    • 違反、未型付け概念、未宣言型、未知ラベル、予約エイリアス競合を確認できます。
    • スキーマモードに左右されない監査・検証に対応しました。
    • 監査結果のページングに対応しました。
    • MCPツールから監査・検証を実行できるようになりました。
    • 読み取り操作として利用でき、レプリカ環境にも対応しました。
  • テスト

    • API、MCP連携、権限、ページング、非永続検証を検証しました。

Adds the read-only standing audit and never-persisted dry-run over
ADR 0009's schema document (#385, S7 of #218's split §10). Both share
one judgment built on the existing schema_issues/SchemaEnv pure check
(S3, #381) so a finding here is exactly what strict would refuse for
the same fact, and both judge mode-independently — pre-existing
violations are otherwise invisible once a context sits in off/warn.

Claude-Session: https://claude.ai/code/session_01FJSVDt6KNgjbjdtJeLxMC9
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ac0591e-835b-4ec9-a60c-83a4f606a2be

📥 Commits

Reviewing files that changed from the base of the PR and between 0f2ffb4 and 3929e4a.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • src/api/schema.rs
  • src/mcp.rs
  • src/schema.rs
  • src/schema/check.rs
  • tests/http_api/key_scopes_cross_context.rs
  • tests/http_api/schema_audit.rs
🚧 Files skipped from review as they are similar to previous changes (7)
  • tests/http_api/key_scopes_cross_context.rs
  • src/mcp.rs
  • CHANGELOG.md
  • src/schema.rs
  • tests/http_api/schema_audit.rs
  • src/schema/check.rs
  • src/api/schema.rs

📝 Walkthrough

Walkthrough

スキーマ監査APIと提案スキーマ検証APIを追加しました。共通検査エンジンがライブ関連付けと提案文書を評価します。HTTPルート、Read権限、heavy-operation limiter、MCPツール、統合テストを追加しました。

Changes

スキーマ監査と検証

Layer / File(s) Summary
スキーマ検査契約とパス生成
src/schema.rs, src/schema/check.rs
IssuePath列挙型でリクエストベースとエッジベース問題パスを型安全に分岐しました。InstalledSchema::enforcingメソッドはOffモードをStrict相当として扱う複製済みArcを返します。
監査エンジンと診断データモデル
src/api/schema.rs, src/context/query.rs, src/schema/check.rs
ライブ関連付けを走査し、違反、未型付け概念、未宣言型、未知ラベル、予約エイリアス競合を共通収集するschema_auditを実装しました。Context::all_associationsメソッドは全エッジを挿入順で列挙します。AuditNamesAuditAliasesは総数を保持しつつ最大100件に制限します。
HTTPハンドラー(監査と検証)
src/api/schema.rs, src/api.rs
audit_schemaハンドラーはインストール済みスキーマからライブ関連付けを監査します。validate_schemaハンドラーは提案文書を永続化せず評価します。両方が共通schema_auditエンジンを使用し、同一の診断結果形式を返します。
ルート、認証、制限、MCP統合
src/main.rs, src/auth.rs, src/limits.rs, src/mcp.rs, src/mcp/route.rs, src/mcp/schema.rs, src/api/associations.rs, src/ingest.rs
HTTPエンドポイントを無条件heavy-operation limiterに追加しました。両ルートをRead権限として分類しました。MCP ツール定義とルーティングを追加し、limitafterを転送しました。既存呼び出しをIssuePath::Request型に更新しました。
統合テストと機能検証
tests/http_api/schema_audit.rs, tests/http_api/main.rs, tests/http_api/mcp_basics.rs, tests/http_api/key_scopes_cross_context.rs, tests/http_api/replication.rs, src/auth.rs, CHANGELOG.md
404エラー、モード非依存違反検出、診断分類、ページング、非永続性、独立評価、無効入力拒否を検証しました。HTTP API、MCP、認証キースコープ、レプリカでのエンドツーエンド動作を確認しました。

Estimated code review effort: 4 (Complex) | ~50 minutes

Possibly related issues

Possibly related PRs

  • t0k0sh1/taguru#392 — 共有schema_issuesIssuePath、予約エイリアス競合処理の基盤を提供しました。
  • t0k0sh1/taguru#390InstalledSchemaSchemaDocument、スキーマ管理状態を導入しました。
  • t0k0sh1/taguru#391schemaモジュールの状態管理APIを実装しました。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは、追加された2つのスキーマAPIを明確に示し、主な変更内容を正確に要約しています。
Linked Issues check ✅ Passed 実装は、ライブ監査、非永続化検証、共有検査ロジック、Read権限、heavy operation、MCP連携など、Issue #385の要件を満たしています
Out of Scope Changes check ✅ Passed 変更はIssue #385のAPI、共通検査、権限、制限、MCP連携、テストに関連し、明らかな範囲外の変更はありません。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 385-schema-audit-validate

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (3)
src/api/schema.rs (2)

239-247: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

reserved_alias_conflicts だけが上限を持ちません。

untyped_conceptsundeclared_typesunknown_labelsMAX_AUDIT_NAMES で上限を持ちます。reserved_alias_conflicts はライブの label_aliases() の絞り込み結果をそのまま返します。件数に上限がありません。

validate_schema はスキーマ未インストールのコンテキストにも適用できます。そのコンテキストでは PUT /schema の install 時ガードが一度も動いていません。予約ラベルへ解決するエイリアスが多数存在すると、レスポンスが非有界に大きくなります。

他の3セクションと同じく AuditNames へ揃えるか、上限を持たない理由を doc コメントに追記してください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/schema.rs` around lines 239 - 247, Align reserved_alias_conflicts
with the bounded audit sections by collecting it through AuditNames and
enforcing MAX_AUDIT_NAMES while filtering label_aliases() for aliases resolving
to schema:type. Preserve the existing alias-to-canonical mapping and response
behavior for retained entries.

329-350: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

fact_edgesfact_ops が同じ文字列を二重に保持します。

ループは各 fact エッジについて subjectlabelobjectAssocOp へ clone し、その後 Association 本体も fact_edges へ push します。エッジ数を N とすると、3N 回の追加 String アロケーションが発生します。この経路は O(edges) の heavy operation であり、大きなコンテキストではこのコピーがピークメモリを押し上げます。

fact_edges を先に確定し、fact_ops をその借用から組み立てる方法は SchemaEnv::build&[AssocOp] シグネチャと衝突します。現状の構造を保つ場合は、少なくとも fact_edgesfact_ops の両方に Vec::with_capacity を与えて再アロケーションを減らしてください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/schema.rs` around lines 329 - 350, Update the fact collection setup
in SchemaEnv::build to initialize both fact_edges and fact_ops with capacity
based on the live association count before the loop, while preserving the
existing ownership and cloning behavior.
src/schema/check.rs (1)

368-400: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

IssuePath::Edge のパス生成にユニットテストがありません。

このモジュールのテストはすべて IssuePath::Request を使います。Edge バリアントが subject / object / label の裸のパスを返すことは、ここでは検証されていません。associations_field の分岐が壊れても、このモジュールのテストは失敗しません。

domain_violation_is_reported_on_the_subject_path と対になる Edge 版のテストを追加してください。統合テスト側で同じ契約を検証済みであれば、この指摘は不要です。

♻️ 追加テストの例
    #[test]
    fn the_edge_path_names_the_side_alone() {
        let mut context = Context::default();
        context
            .associate_from("山田太郎", SCHEMA_TYPE_LABEL, "Person", 1.0, "a.md", None)
            .unwrap();
        let schema = installed(doc(SchemaMode::Strict, false));
        let ops = [assoc_op("山田太郎", "杜氏", "鈴木一郎", 1.0, None)];
        let env = env(&context, schema, &ops);
        let check = schema_issues(&env, &ops, IssuePath::Edge);
        assert_eq!(check.violations[0].path, "subject");
    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/schema/check.rs` around lines 368 - 400, Add a unit test alongside
domain_violation_is_reported_on_the_subject_path that invokes schema_issues with
IssuePath::Edge and verifies the reported violation path is the bare side name,
such as "subject". Reuse the existing context, schema, operation, and helper
setup patterns, and ensure the test exercises the Edge branch rather than
IssuePath::Request.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 24-32: Update the changelog sentence describing the DriftAudit
response to say “Five candidates-not-verdicts sections,” matching the five
listed sections: violations, untyped_concepts, undeclared_types, unknown_labels,
and reserved_alias_conflicts.

In `@src/api/schema.rs`:
- Around line 368-387: SchemaEnv::build を呼び出す前に deadline.expired()
を確認し、期限切れなら既存の AccessError::DeadlineExceeded を返すよう更新してください。SchemaEnv::build 後の
violation ループと各エッジのチェックは変更せず、build 前の単一チェックのみ追加してください。

In `@src/main.rs`:
- Around line 781-785: schema/audit と schema/validate の wire
契約を追加し、DriftAudit、ページング、および document・limit・after の形状と転送を固定してください。src/main.rs
のルート登録は維持し、tests/http_api/contract.rs に両 HTTP 操作のプローブを追加し、対応する HTTP/MCP fixture
と shapes.json の必須入力を更新してください。src/mcp/route.rs の該当 MCP ルートおよび src/mcp/schema.rs
の該当スキーマ定義も契約対象として fixture・形状に反映し、互換追加のため契約値は bump しないでください。

In `@src/mcp.rs`:
- Around line 610-617: Extend the MCP routing tests around the cases list to
cover the after parameter for both audit_schema and validate_schema. Add
assertions verifying that route_tool forwards after into the HTTP request body,
rather than only validating the input schema. Keep the existing field checks
unchanged for the other tools.

In `@src/schema.rs`:
- Line 274: InstalledSchema の enforcing を self: &Arc<Self>
のメソッドレシーバではなく、Arc<InstalledSchema> を引数に取る関連関数へ変更してください。あわせて、src/api/schema.rs の
enforcing 呼び出しを新しい関連関数形式に更新し、既存の戻り値と動作を維持してください。

In `@tests/http_api/key_scopes_cross_context.rs`:
- Around line 89-105: Extend the key-scope test around the existing GET /schema
404 assertion to configure a schema using the admin key, then call schema/audit
with the reader key rtok and assert a 200 response. Use the existing call helper
and setup flow, while preserving the current schema/validate reader-key
assertion.

In `@tests/http_api/schema_audit.rs`:
- Around line 109-117: Update tests/http_api/schema_audit.rs lines 109-117 to
store each complete audit response and assert all mode responses are identical,
rather than comparing only total. Update lines 410-416 to compare the complete
audit responses for without and with cases, ensuring every section remains
independent of mode and resident schema effects.
- Around line 1-8: Add schema audit coverage in the tests around schema_audit to
define a deprecated relation whose use would normally produce a domain or range
violation, then assert that it is omitted from both violations and total. Ensure
the test exercises the audit endpoint’s filtering behavior and would fail if
deprecated relations are included again.
- Around line 268-288: Strengthen the pagination assertions in the schema audit
test by validating each violation’s weight and association identity, not only
page lengths. Using the existing first_matches and second_matches results,
assert that 弟子1, 弟子2, and 弟子3 appear in severity order exactly once across both
pages, confirming the cursor after the second first-page result resumes at the
correct item without duplication.

---

Nitpick comments:
In `@src/api/schema.rs`:
- Around line 239-247: Align reserved_alias_conflicts with the bounded audit
sections by collecting it through AuditNames and enforcing MAX_AUDIT_NAMES while
filtering label_aliases() for aliases resolving to schema:type. Preserve the
existing alias-to-canonical mapping and response behavior for retained entries.
- Around line 329-350: Update the fact collection setup in SchemaEnv::build to
initialize both fact_edges and fact_ops with capacity based on the live
association count before the loop, while preserving the existing ownership and
cloning behavior.

In `@src/schema/check.rs`:
- Around line 368-400: Add a unit test alongside
domain_violation_is_reported_on_the_subject_path that invokes schema_issues with
IssuePath::Edge and verifies the reported violation path is the bare side name,
such as "subject". Reuse the existing context, schema, operation, and helper
setup patterns, and ensure the test exercises the Edge branch rather than
IssuePath::Request.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d9839344-0431-485f-9090-10ebf51cffcf

📥 Commits

Reviewing files that changed from the base of the PR and between 7e79ccf and 0f2ffb4.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • src/api.rs
  • src/api/associations.rs
  • src/api/schema.rs
  • src/auth.rs
  • src/context/query.rs
  • src/ingest.rs
  • src/limits.rs
  • src/main.rs
  • src/mcp.rs
  • src/mcp/route.rs
  • src/mcp/schema.rs
  • src/schema.rs
  • src/schema/check.rs
  • tests/http_api/key_scopes_cross_context.rs
  • tests/http_api/main.rs
  • tests/http_api/mcp_basics.rs
  • tests/http_api/replication.rs
  • tests/http_api/schema_audit.rs

Comment thread CHANGELOG.md Outdated
Comment thread src/api/schema.rs
Comment thread src/main.rs
Comment thread src/mcp.rs
Comment thread src/schema.rs Outdated
Comment thread tests/http_api/key_scopes_cross_context.rs
Comment thread tests/http_api/schema_audit.rs
Comment thread tests/http_api/schema_audit.rs Outdated
Comment thread tests/http_api/schema_audit.rs Outdated
Bounds reserved_alias_conflicts like the other audit sections, recovers
enforcing() to a plain associated function instead of an Arc-receiver
method, pre-flights the deadline before SchemaEnv::build's second graph
read, and pre-sizes the fact_edges/fact_ops buffers. Strengthens the
integration tests (full-response mode-invariance and validate parity
comparisons, exact pagination identity) and adds the missing
IssuePath::Edge/after-forwarding unit test coverage. Skips the
"deprecated relation" audit suggestion (no such field exists on the
schema document yet, per ADR 0009 §9.2) and the wire-contract fixture
suggestion (the existing vocabulary/audit and drift/audit routes carry
no such fixture either).

Claude-Session: https://claude.ai/code/session_01FJSVDt6KNgjbjdtJeLxMC9
@t0k0sh1
t0k0sh1 merged commit 0972b56 into main Aug 4, 2026
9 checks passed
@t0k0sh1
t0k0sh1 deleted the 385-schema-audit-validate branch August 4, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

schema: POST /contexts/{name}/schema/validate and /schema/audit

1 participant