- declare namespace preview tables and indexes in the runtime schema
- allow capability audit records before a control space exists
- preserve namespace audit details in the sanitized claims summary
- add schema, migration, and audit regression coverage
Workflow KnowledgeFS retrieval nodes ran through `retrieval-tests`, which
never wrote an AnswerTrace or an overview event, so their queries were
missing from the retrieval history and from the space overview; the history
also only ever showed each member their own traces.
- AnswerTrace gains a `source` (retrieval_test | workflow | service_api |
agent | mcp; migration 0051_answer_trace_source) derived from the
Capability v2 caller kind. The retrieval-tests route records one trace per
run (stages, evidence bundle, profile metadata), returns its id as
`answerTraceId`, and the workflow node's failed-retrieval capture attaches
to that trace instead of creating a second record.
- The quality trace list exposes and filters by `source`; traces from other
caller kinds are visible to any current reader of the space, and counts and
scores fall back to the evidence embedded in the trace when no bundle row
exists.
- Overview accounting: retrieval-tests and Research tasks now emit
`query.requested`, and the Research job state machine emits
`query.completed` / `query.failed` on terminal stages (wired for both the
in-process gateway and the durable runtime), so query volume, answer rate
and outcomes include every caller. Activity details keep `source` and
`taskKind`.
- Console and service trace routes accept a `source` filter; the retrieval
test page shows a source badge and an all / retrieval tests / workflow
filter, with translations for every locale.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
- create website preview jobs before a knowledge space exists
- persist crawled page content in KnowledgeFS object storage
- import selected pages using preview job and page IDs
- validate preview ownership, expiry, and configuration fingerprint
- clean up preview content after cancellation, expiry, or consumption
- add namespace preview routes, capabilities, migrations, and contracts
- keep online document and drive flows unchanged
- create website preview jobs before a knowledge space exists
- persist crawled page content in KnowledgeFS object storage
- import selected pages using preview job and page IDs
- validate preview ownership, expiry, and configuration fingerprint
- clean up preview content after cancellation, expiry, or consumption
- add namespace preview routes, capabilities, migrations, and contracts
- keep online document and drive flows unchanged
The legacy dataset console rate limits every mutating, download, and
retrieval route and the dataset service API limits every request, while
KnowledgeFS only covered uploads and query admission. Apply the knowledge
rate limit to all space-scoped POST/PUT/PATCH/DELETE console routes, the
document downloads, and research/query entrypoints (workspace-level source
previews, staged-upload discards, the deprecated buffered query route, and
the internal stream transport stay exempt). Extract the service API check
into `check_knowledge_rate_limit` and call it from the KnowledgeFS profile
helper so all service routes share the legacy per-workspace limit.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
KnowledgeFS spaces used their own `knowledge_space_*` RBAC vocabulary, so
workspace roles configured for knowledge bases did not apply to them. Reuse
the legacy `dataset_*` permission points instead, following the mapping the
dataset console already applies:
- read -> dataset_readonly
- create -> dataset_create_and_management
- edit / document write -> dataset_edit
- delete -> dataset_delete
- access config -> dataset_access_config
- query / research / trace detail -> dataset_retrieval_recall
The enterprise `/knowledge-fs/permission-keys/batch` lookup now answers in
that vocabulary and is translated back into the product capabilities the
console exposes as `permission_keys`, so the web stays unchanged; the
historical `knowledge_space_*` keys remain accepted during the transition.
Workspace-level checks send the mapped dataset scene with
`resource_type=dataset`, and the RBAC-disabled fallback grants every dataset
point KnowledgeFS consults.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
Migration 9a4e7d1c2b60 (dataset API key binding resource type) is the new
single head after c3f1a9b2e6d4; update the merge-head guard accordingly.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
Legacy knowledge bases (`datasets`) and KnowledgeFS spaces
(`knowledge_fs_control_spaces`) live in different tables, so a dataset API
key binding could only ever name a legacy dataset and the KnowledgeFS service
API never consulted bindings at all: a key scoped to specific knowledge bases
still reached every KnowledgeFS space in the workspace.
- Bindings carry a `resource_type` (`dataset` | `knowledge_fs_space`) and a
nullable `control_space_id` (migration 9a4e7d1c2b60, existing rows stay
`dataset`), with a CHECK that exactly one id column matches the type.
- `dataset_api_key_service` exposes the key scope by kind, validates and
binds KnowledgeFS spaces (tenant-owned, not deleting/deleted), and cleans up
keys scoped only to a space when its deletion is requested. The orphan-key
cleanup is now NULL-safe so a space binding keeps a key alive.
- Legacy dataset routes only honour `dataset` bindings; the KnowledgeFS
authorization service only honours `knowledge_fs_space` bindings and raises
a scope error that the service API maps to 403 (unknown keys stay 401).
- Console key creation accepts `knowledge_space_ids`; list/create responses
return them next to `dataset_ids`.
- The web scope picker lists KnowledgeFS spaces alongside legacy datasets
when KnowledgeFS is enabled and submits the ids by kind; the scope column
counts both.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
Drop the deprecated `POST /knowledge-fs/spaces/<id>/queries` route and the
deprecated buffered `POST .../documents` upload from the service API. Both
only ever failed closed; queries go through admission + the query stream,
documents through the durable source import flow. Regenerate the service
contracts and markdown docs accordingly.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
- retry semantic chunking when the LLM returns an invalid schema
- add corrective schema instructions to retry prompts
- remove capability grant foreign keys from durable deletion records
- preserve capability grant IDs as immutable audit provenance
- add migration and regression coverage
- retry semantic chunking when the LLM returns an invalid schema
- add corrective schema instructions to retry prompts
- remove capability grant foreign keys from durable deletion records
- preserve capability grant IDs as immutable audit provenance
- add migration and regression coverage
Every document-processing failure surfaced as "the document could not be
processed", and every data-source failure as "the source could not be read",
because the root cause was erased at three points: the compilation classifier
collapsed any coded-but-non-retryable error into DOCUMENT_COMPILATION_FAILED,
datasource runtime errors were reduced to per-operation constants, and the
console mapped dozens of codes onto a handful of generic sentences without the
stage or a support reference.
- knowledge-fs: keep the specific public code for any coded error in the
compilation classifier (retry follows the error or the catalog policy), tag
previously uncoded failures (semantic chunking output, embedding dimension,
PDF rendering, lease loss, generation model, unsupported file type) with
public codes, give embedding provider errors their own codes instead of the
parser's, alias datasource runtime codes, and register 17 catalog entries
(model response invalid, parser unsupported type, PDF render, crawl page
not found, provider timeout/unavailable/rejected, content too large, ...).
- api: extend the public error-code enum (including the missing
DOCUMENT_PARSER_TIMEOUT) and regenerate the contracts.
- web: per-code copy that says what happened and what to do, in all 24
locales, plus a "failed while <stage> · reference <id>" line under each
failed task in the background-task drawer and the document task list.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
The KnowledgeFS retrieval node treated the query text as mandatory even though
a query image is a complete input on its own. Text and image are now
alternatives: the node needs at least one of them, never both.
- web: drop the required mark from the query text field; the checklist fails
only when neither variable is bound (new i18n message in every locale).
- api: make `query_variable_selector` optional with a model-level rule that
one of the two selectors must be set, and only map the query variable when
it is bound. At runtime an empty text without images is a configuration
error; an image-only query retrieves with an empty text, merges spaces on
their own scores instead of a text reranker, skips automatic metadata
extraction, and skips the text-based failed-query capture.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc
A retrieval test record could be flagged as a bad case any number of times,
piling duplicate open cases onto the quality page. Refuse to file another bad
case while the trace already has one that is open or replaying, and let the
retrieval test page know about it.
- knowledge-fs: `createBadCase` looks up an unresolved case for the trace
inside its transaction and throws `QualityBadCaseAlreadyOpenError`; the
create route answers 409 with `QUALITY_BAD_CASE_ALREADY_OPEN`. Quality trace
list items expose `openBadCaseId`.
- api: pass `open_bad_case_id` through the console trace response;
regenerate the contracts.
- web: show the saved-as-bad-case state instead of the flag action when the
selected trace already has an unresolved case, treat a 409 on flagging the
same way, and refresh the history so the state follows the server.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015zw5G5SX3HmVfnZof6YWAc