Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,36 @@ Entries that change an on-disk format or a response shape say so.
## [Unreleased]

### Added
- `POST /contexts/{name}/schema/audit` and `POST
/contexts/{name}/schema/validate` (#385, S7 of #218's ADR 0009 split
§10). `audit` judges every live association against the resident
document; `validate` takes a *proposed* document instead and never
persists it — the pre-flight §7.1 promises before a `strict` flip.
Both share one judgment (`schema_audit`, `src/api/schema.rs`) built
on the same `schema_issues`/`SchemaEnv` pure check every write
entrance already uses (S3, #381), so a finding here is exactly what
`strict` would refuse for the identical fact. Deliberately
mode-independent: §7.1's whole reason for this route to exist is that
pre-existing violations are otherwise invisible, so `audit`/`validate`
judge as `strict` would regardless of the document's actual `mode` —
an `off` or `warn` context reports the same violations a `strict` one
does. Five candidates-not-verdicts sections in one `DriftAudit`-shaped
response, framed exactly like `audit_vocabulary`'s own doc — nothing
is ever auto-applied: `violations` (domain/range mismatches, the only
section that pages, worst-magnitude-first like every other match
list), `untyped_concepts`, `undeclared_types` (§6.2, always reported
regardless of `closed_labels`), `unknown_labels` (§6.4, only under
`closed_labels`, never naming `schema:type` itself), and
`reserved_alias_conflicts` (§6.3 guard 2's install-time bullet, read
back — only reachable through `validate`, since `PUT /schema` itself
already refuses to install over such a conflict). Deprecated-relation
usage is explicitly **not** in scope here — §9.2 defers it until a
follow-up ADR gives the document a field to mark a relation
deprecated. Both routes are `Role::Read` and O(edges) with no cheap
variant, joining the unconditional heavy-ops group beside
`audit_vocabulary`/`compact_context` rather than `audit_drift`'s
conditional-extension pattern. `audit_schema`/`validate_schema` MCP
tools round-trip onto the same two routes.
- The `taguru_schema` export/import stream record and its replication
parity (#384, S6 of #218's ADR 0009 split §13). `export::render`
emits it as the FIRST line of a context's stream, only when the
Expand Down
2 changes: 1 addition & 1 deletion src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub use import::{
pub(crate) use import::{import_outcome, schema_import_outcome};
pub use recall::{cross_query, cross_recall, query, recall};
pub use resolve::{explain_resolve, explain_resolve_label, resolve, resolve_label};
pub use schema::{get_schema, put_schema};
pub use schema::{audit_schema, get_schema, put_schema, validate_schema};
pub use sources::{
citation, cross_search_passages, explain_search_passages, list_sources, lookup_passages,
retract_source, search_passages, store_passages,
Expand Down
4 changes: 2 additions & 2 deletions src/api/associations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use taguru::deadline::Deadline;

use crate::metrics::ErrorKind;
use crate::registry::{AppState, AssocOp};
use crate::schema::{SchemaCheckInput, SchemaEnv, SchemaMode, schema_issues};
use crate::schema::{IssuePath, SchemaCheckInput, SchemaEnv, SchemaMode, schema_issues};

use super::{
AppJson, AppPath, ErrorCode, Issue, MAX_ASSOCIATION_WEIGHT, MAX_ASSOCIATIONS_PER_REQUEST,
Expand Down Expand Up @@ -295,7 +295,7 @@ pub async fn add_associations(
Ok(env) => env,
Err(failure) => return access_error(&state, failure, &name, started_at),
};
let check = schema_issues(&env, &associations, "");
let check = schema_issues(&env, &associations, IssuePath::Request { prefix: "" });
// ADR 0009 §6.3 guard 2: a reserved-label conflict refuses
// regardless of mode — this route has no inline `labels`
// declaration today, so `reserved` is always empty in
Expand Down
Loading