Commit graph

1479 commits

Author SHA1 Message Date
cybermaggedon
bdfdbb3c1f
feat: add Docling-based document decoder as alternative to unstructured (#1054)
Add trustgraph-docling package providing a document decoder powered by
IBM's Docling library. Supports PDF, DOCX, XLSX, PPTX, HTML, Markdown,
and CSV with two chunking modes:

- page mode (default): groups output by page for page-based formats,
  emits TextDocument messages for the existing downstream chunker
- hybrid mode: uses Docling's HybridChunker for structure-aware
  semantic chunking, emits Chunk messages directly

Tables are preserved as HTML markup. Images are stored in the librarian
with provenance but excluded from the text pipeline. Full provenance
chain is maintained for explainability tracing.

Includes Containerfile, CI/CD integration (PR checks and release
workflows), Makefile targets, and tech spec documentation.

Added unit tests for the package.
2026-07-20 21:25:33 +01:00
01AtharvR
6d51773e00 Sanitize workspace name used as Cassandra keyspace (#1043) (#1053) 2026-07-20 10:34:55 +01:00
cybermaggedon
80ef18a0be
fix: update knowledge manager tests for per-workspace librarian clients (#1050)
Update test fixtures to use librarian_clients dict keyed by workspace
instead of the removed librarian kwarg. Adjust mock references and
add empty list-children response for recursive _stream_doc_tree.
2026-07-16 09:46:48 +01:00
cybermaggedon
60529c3b3d
fix: knowledge core round-trip for workspace-scoped librarian and all term types (#1049)
Change librarian from a single shared client to per-workspace clients,
ensuring knowledge core get/put operations use workspace-scoped queues.
LibrarianClient is now created in on_workspace_created and cleaned up
in on_workspace_deleted.

Fix term_to_tuple/tuple_to_term to handle TRIPLE and BLANK term types.
Previously only IRI and LITERAL were supported, causing ~1000 edges
(ns/contains with quoted triple objects) to be silently lost during
Cassandra storage. TRIPLE terms are now JSON-serialized with a
<<TRIPLE>> marker prefix, BLANK terms with <<BLANK>>.

Make document tree export recursive via _stream_doc_tree so that
grandchild documents (chunks under pages) are included in knowledge
core export. Without this, explainability source links break after
a get/put/load round-trip because chunk documents are not restored.

Add error response encoding to KnowledgeResponseTranslator.encode()
and fix encode_with_completion to treat error responses as non-final.
Change KnowledgeResponse.ids from list[str] with default factory to
Optional[list[str]] so list responses can be distinguished from empty
responses. Add error display to get_kg_core CLI.
2026-07-16 00:31:47 +01:00
cybermaggedon
a5a302b0d0
feat: preserve RDF language tags and datatypes through ingestion and query (#1046)
Language tags and XSD datatypes on RDF literals were being silently
dropped at multiple points in the pipeline, making SPARQL FILTER(LANG())
queries and multilingual datasets non-functional.

Ingestion fixes:
- load_knowledge.py and load_turtle.py now extract .language and
  .datatype from rdflib Literal objects instead of discarding them
- Triple dataclass gains optional o_datatype and o_language fields
- _string_to_term() emits "dt" and "ln" in the wire format
- AsyncBulkClient uses the same term serialization as BulkClient

Query fix:
- TriplesClient.query_gen() preserves Term objects directly instead of
  converting through Uri/Literal (which are str subclasses with no room
  for language metadata), enabling SPARQL LANG() filters to work
2026-07-15 10:12:46 +01:00
cybermaggedon
77cb2f548e
fix: index literal objects in entity table for object-based graph queries (#1041)
Literal objects (e.g. rdfs:label values) were not being inserted into the
quads_by_entity table with role='O', so queries like `tg-query-graph -o
MIL-HDBK-516D` returned no results even though the triple existed.

Removed the otype guard that skipped entity row insertion for literals in
both insert() and async_insert(). Also updated delete_collection() and
async_delete_collection() to include literal objects in entity partition
cleanup.

Existing data requires re-ingestion for old literal objects to become
queryable by object value.
2026-07-13 20:03:00 +01:00
01AtharvR
b1d1833234
Replace bare except with specific exceptions in api layer (#783) (#1039) 2026-07-13 12:06:23 +01:00
Sunny Yang
40f01c123b
feat: pluggable image-to-text service with OpenAI vision backend (#1038)
Adds a full-stack image description service: schema, base class,                                                                  
OpenAI backend, gateway dispatch, client APIs (sync/async REST +
websocket), tg-describe-image CLI, IAM capability, and specs.                                                                     
                                                                                                                                    
Closes #879
2026-07-12 12:47:04 +01:00
cybermaggedon
9136526863
feat: LLM-native structured output via JSON schema enforcement (#1037)
Thread existing JSON schemas from prompt definitions through the
text-completion service to LLM backends' native structured output
APIs. When a prompt has response-type "json" and a strict-mode
compatible schema, the LLM constrains token selection at the logit
level to guarantee schema-valid output.

Wire-level changes:
- Add response_format and schema fields to TextCompletionRequest
- Update translator to encode/decode new fields
- Pass new fields through LlmService, TextCompletionClient, and
  PromptManager

Runtime schema compatibility checker:
- New is_strict_mode_compatible() utility validates schemas against
  LLM provider constraints (additionalProperties, required fields,
  no unsupported constraints, no open-ended objects)
- Per-prompt eligibility decision: compliant schemas use structured
  output, non-compliant schemas fall back to free-text + post-hoc
  validation

LLM backend implementations:
- OpenAI: response_format with json_schema, variant-aware top-level
  array rejection (openai variant blocks, llama/vllm variants allow)
- New vllm variant for the OpenAI backend
- vLLM (dedicated): response_format in raw HTTP body
- Ollama: format=<schema> parameter
- Claude: tool-use trick (forced tool call with schema as input_schema)
- Mistral: native json_schema response_format
- Llamafile, LM Studio: OpenAI SDK response_format
- Azure OpenAI: AzureOpenAI SDK response_format
- Azure serverless: response_format in raw HTTP body
- TGI: response_format in raw HTTP body
- VertexAI Gemini: response_mime_type + response_schema
- VertexAI Claude: tool-use trick
- Google AI Studio: response_mime_type + response_schema
- Bedrock, Cohere: signature-only (no structured output yet)

Post-hoc jsonschema.validate() retained as defence-in-depth.

Tech spec added: docs/tech-specs/structured-output.md

Update tests
2026-07-10 15:28:56 +01:00
Wei Xu
f106ae2103
fix: preserve non-ASCII entity names in ontology URI normalization (#1036)
The entity URI normalizer stripped every non-ASCII character via the
ASCII-only patterns `[^a-z0-9\-.]` and `[^a-z0-9\-]`. For non-Latin
entity names (e.g. Chinese), this deleted the entire name, so distinct
entities collapsed onto the same URI (".../<ontology>/-"), silently
merging unrelated nodes and breaking OntoRAG for non-English content.

Switch both filters to `[^\w\-.]` / `[^\w\-]`. In Python 3, `\w` is
Unicode-aware for str patterns, so non-ASCII letters (CJK, etc.) are
preserved while punctuation and symbols are still removed. ASCII
behaviour is unchanged: names are lowercased and underscores converted
to hyphens before the filter runs, so for ASCII input the patterns are
equivalent to the originals.

Adds tests covering ASCII regression guards and non-ASCII names/types,
including the core case that two distinct Chinese entities must not
collapse onto the same URI.

Co-authored-by: arthurxuwei <5179840+arthurxuwei@users.noreply.github.com>
2026-07-09 00:05:35 +01:00
Sunny Yang
e9c6a850ad
feat: structured source document references in graph-rag responses (#1035) 2026-07-08 23:59:56 +01:00
cybermaggedon
0374098ee9
fix: lazily retry signing key fetch on JWT authentication (#1032)
If the gateway started before IAM was ready and exhausted its startup
retries, _signing_public_pem stayed None and all JWT authentication
permanently 401'd with no recovery path short of a restart. Now
_verify_jwt retries the fetch once on demand, so the gateway self-heals
as soon as IAM becomes available.
2026-07-07 16:00:34 +01:00
Keshav
f76f2abe08
feat: make fetch timeout for chunks configurable (#1031)
* tests: processor accepts default and overrides of fetch_chunk_timeout

* feat: configure fetch timeout for chunks from librarian
2026-07-07 15:55:33 +01:00
Sunny Yang
2bdc930b2a
feat: hybrid retrieval (BM25 + vector RRF fusion) for document-RAG (#875) (#1030)
Adds a sparse keyword retrieval path beside the existing vector path in
document-RAG, fused by weighted Reciprocal Rank Fusion on chunk_id, behind
--retrieval-mode (vector | keyword | hybrid, default vector).

The keyword index is a new pluggable service (KeywordIndexService /
KeywordIndexClientSpec); the first backend is SQLite FTS5, consuming Chunk
messages off the ingestion stream and answering BM25 queries from one
process, since the index is a single local file. Query text is sanitized
into per-term quoted phrases (raw text is not valid FTS5 syntax), which
also makes dotted clause numbers and error codes exact-match without a
trigram index. Indexes are scoped per (workspace, collection) and dropped
on collection deletion.

The keyword-index client spec is only registered when the sparse path is
enabled, so existing flow definitions without keyword-index queues are
untouched; with retrieval_mode=vector the retrieval path is unchanged. In
hybrid mode a keyword-path failure degrades to vector-only.
2026-07-07 12:54:02 +01:00
Cyber MacGeddon
e5206bddd0 Merge branch 'master' into release/v2.7 2026-07-06 10:54:01 +01:00
Cyber MacGeddon
5a1b42ab33 Merge branch 'release/v2.6' 2026-07-06 10:53:47 +01:00
cybermaggedon
a84cffa485 fix: handle missing time field in library API document/processing responses (#1028)
Documents and processing records without a stored time field caused a
KeyError crash in get_documents and list_children. Use optional access
so time resolves to None instead of failing.
2026-07-06 10:48:53 +01:00
Sunny Yang
0b6bae02f5 feat: export/import workspace knowledge in .tgx bundles (#877 Phase 2) (#1024)
* feat: streaming N-Quads serializer for wire-format triples

Groundwork for Phase 2 of #877 (knowledge export). Hand-rolled
N-Triples term encoding: rdflib's term.n3() emits Turtle-style forms
(numeric shorthand, unescaped newlines) that are invalid in
line-oriented N-Quads, so literals are escaped per the ECHAR grammar
and IRIs validated for representability. Round-trip tests parse the
output back with rdflib's nquads parser and compare term-for-term.

* feat: export/import workspace knowledge in .tgx bundles (#877)

Phase 2 of the workspace bundle commands: tg-export-workspace now
includes the workspace's knowledge by default — per-collection
knowledge-graph triples as N-Quads (the collection names the graph,
streamed through a tempfile so memory stays flat regardless of
knowledge-base size) and the document library (metadata plus content,
fetched one document at a time). --config-only skips knowledge on both
sides; --triples-limit bounds very large graphs; -f/--flow-id selects
the flow the triples services run through.

tg-import-workspace streams triples back through the bulk import per
collection and recreates library documents (children after parents).
Knowledge import is additive, unlike config's skip-existing semantics.
Embedding vectors are not carried in bundles: --process re-runs
imported documents through the flow, which regenerates extraction
output and embeddings; --process-collection targets it.

Round-trip covered by unit tests over real archives: export with a
mocked Api, re-import, and assert the bulk triples stream and library
add calls reproduce the original values (including datatyped literals
via the N-Quads path).
2026-07-06 10:48:41 +01:00
cybermaggedon
d5f3b6d9f6
feat: add structured audit event system (#1027)
Add a complete audit event pipeline that emits structured, machine-
parseable events for every gateway request and IAM decision.

Schema and publisher:
- AuditEvent dataclass and notify-class queue (audit_events_queue)
- AuditPublisher utility: fire-and-forget emission with envelope
  (schema_version, event_id, event_type, timestamp, producer)
- New request_id and client_ip fields on IamRequest for correlation

Gateway (gateway.request events):
- aiohttp middleware assigns request_id, captures timing/status/sizes
  and emits an event after every HTTP request completes
- IamAuth.authenticate annotates the request with identity
- Main endpoint handlers annotate capability and workspace
- request_id and client_ip forwarded to IAM on authenticate/authorise

IAM service (iam.authenticate, iam.authorise, iam.management events):
- Emits iam.authenticate for resolve-api-key, login, anonymous auth
- Emits iam.authorise for authorise and authorise-many decisions
- Emits iam.management for user/workspace/key mutations
- All events include request_id for correlation with gateway events

Design: events land on a pub/sub notify topic — non-persistent,
per-subscriber delivery. If no audit consumer is deployed, events
are silently discarded. Storage, retention, and alerting are
consumer-side concerns outside this boundary.

Added unit tests for the publisher and gateway middleware, unit
tests for IAM audit emission, and a contract test for the AuditEvent
schema.

Tech spec: docs/tech-specs/audit-events.md
2026-07-06 10:47:49 +01:00
cybermaggedon
08f69007c9
fix: handle missing time field in library API document/processing responses (#1028)
Documents and processing records without a stored time field caused a
KeyError crash in get_documents and list_children. Use optional access
so time resolves to None instead of failing.
2026-07-06 10:47:24 +01:00
Sunny Yang
cfbd5b9079
feat: export/import workspace knowledge in .tgx bundles (#877 Phase 2) (#1024)
* feat: streaming N-Quads serializer for wire-format triples

Groundwork for Phase 2 of #877 (knowledge export). Hand-rolled
N-Triples term encoding: rdflib's term.n3() emits Turtle-style forms
(numeric shorthand, unescaped newlines) that are invalid in
line-oriented N-Quads, so literals are escaped per the ECHAR grammar
and IRIs validated for representability. Round-trip tests parse the
output back with rdflib's nquads parser and compare term-for-term.

* feat: export/import workspace knowledge in .tgx bundles (#877)

Phase 2 of the workspace bundle commands: tg-export-workspace now
includes the workspace's knowledge by default — per-collection
knowledge-graph triples as N-Quads (the collection names the graph,
streamed through a tempfile so memory stays flat regardless of
knowledge-base size) and the document library (metadata plus content,
fetched one document at a time). --config-only skips knowledge on both
sides; --triples-limit bounds very large graphs; -f/--flow-id selects
the flow the triples services run through.

tg-import-workspace streams triples back through the bulk import per
collection and recreates library documents (children after parents).
Knowledge import is additive, unlike config's skip-existing semantics.
Embedding vectors are not carried in bundles: --process re-runs
imported documents through the flow, which regenerates extraction
output and embeddings; --process-collection targets it.

Round-trip covered by unit tests over real archives: export with a
mocked Api, re-import, and assert the bulk triples stream and library
add calls reproduce the original values (including datatyped literals
via the N-Quads path).
2026-07-06 10:45:23 +01:00
cybermaggedon
12ea6d46bc
maint: Open 2.7 branch (#1026)
Update package definitions and CI pipeline to refer to 2.7.x
2026-07-06 09:19:12 +01:00
Jack Colquitt
4ac6bc0986
Update section titles and video links in README (#1025) 2026-07-05 07:39:29 -07:00
Jack Colquitt
8d630ef204
Update README with access request link (#1023) 2026-07-03 11:43:56 -07:00
Jack Colquitt
d2a4abb7c5
Revise README with new TrustGraph context description (#1022)
Updated the README to enhance the description of TrustGraph and its features.
2026-07-03 11:40:52 -07:00
cybermaggedon
68e816e65c
feat: filter and cap GraphRAG reranker input across full stack (#1021)
- Filter out RDF/RDFS/OWL schema predicates (rdfs:domain, owl:inverseOf,
  etc.) from hop traversal, keeping rdf:type for data signal
- Skip edges where reranker-visible components are unlabeled IRIs, since
  the cross-encoder cannot meaningfully score raw URIs
- Add max-reranker-input safety cap (default 350) to prevent overloading
  the reranker, applied after filtering for maximum useful candidates
- Expose max-reranker-input as per-request parameter through schema,
  translator, REST API, socket client, CLI, and OpenAPI spec
- Update tests
- Update tech spec
2026-07-03 15:51:04 +01:00
Sunny Yang
76c4763b9b
feat: add tg-export-workspace / tg-import-workspace bundle commands (#877) (#1019)
Phase 1 (config only): export a workspace's full configuration as a
portable .tgx bundle (gzipped tar with manifest.json and one
pretty-printed, self-describing JSON file per config key under
config/<type>/), and import it into another deployment or workspace.

Import defaults to WorkspaceInit's re-run semantics (existing keys kept,
missing keys added; --overwrite replaces), supports --workspace rename,
--dry-run, and --config-only, and refuses to silently drop knowledge
data from future Phase-2 bundles it cannot import yet.
2026-07-03 15:16:39 +01:00
Cyber MacGeddon
508d0bb5c1 Merge branch 'release/v2.6' 2026-07-03 13:45:02 +01:00
cybermaggedon
c05296376e
fix: remove test import (#1017)
Convention in the tests is to just import the libraries as production
code would. This is fragile, and could possibly be used to inject
malicious code in the CI environment.
2026-07-03 13:44:09 +01:00
YingzuoLiu
f04ae5331d
Add diversity-aware selection after Document-RAG reranking (#1014)
* Add Document-RAG diversity selection helper

* Add optional MMR diversity selection after reranking

* Fix Document-RAG diversity test method signatures
2026-07-03 13:35:42 +01:00
cybermaggedon
db7fdbc652
feat: direction-aware reranker text in GraphRAG hop-and-filter (#1016)
The reranker document text now reflects the traversal direction,
showing only the new information relative to the frontier entity:
- From S (subject is frontier): text = "{predicate} {object}"
- From O (object is frontier): text = "{subject} {predicate}"
- From P (predicate is frontier): text = "{subject} {object}"

This eliminates duplicate reranker texts when traversing inward
from shared object nodes (e.g. 18 CPUs all producing identical
"hasSubcategory Processors" text when the subject was dropped).

execute_batch_triple_queries now returns (triple, direction)
tuples so hop_and_filter can select the appropriate text format.

Updates tech spec to document the direction-aware approach.
Adds unit tests for direction tracking and reranker text
construction.
2026-07-02 21:14:47 +01:00
Cyber MacGeddon
4aaa1ce915 Merge branch 'release/v2.6' into master to keep sync. 2026-07-02 14:58:37 +01:00
cybermaggedon
9cf7dcb578
fix: wire variant into remaining streaming integration test mocks (#1013)
Three more streaming tests were missing _wire_variant after the
async for change in create_completion_stream.
2026-07-02 11:14:54 +01:00
Sunny
6c9a545a06
feat: add cross-encoder reranking to Document-RAG with two-limit control (#878) (#1011)
Wire the FlashRank reranker subsystem from #1005 into Document-RAG: after
vector retrieval, over-fetch a wider candidate pool, rerank with the
cross-encoder, and keep the top doc_limit chunks for synthesis.

Per maintainer review, the fetch and select sizes are two caller-controlled
limits rather than one internal heuristic:

- doc_limit:   chunks selected into the synthesis prompt (unchanged meaning).
- fetch_limit: candidate pool pulled from the vector store before reranking.
  0 = derive (OVERFETCH_FACTOR x doc_limit); values below doc_limit are
  raised to it. Lets the caller control how hard the reranker has to work.

Details:
- schema: DocumentRagQuery.fetch_limit (additive, backward compatible).
- document_rag.py / rag.py: fetch_limit resolved in the processor (mirrors
  doc_limit); the core applies the heuristic default and derives synthesis
  provenance from the chunk-selection focus when reranking ran.
- provenance: tg:ChunkSelection focus stage (mirrors tg:EdgeSelection).
- request translator + client SDKs + CLI: fetch-limit / --fetch-limit,
  threaded exactly like doc_limit and the GraphRAG limits.
- tests: no-op identity, over-fetch/narrow, explicit fetch_limit, heuristic
  default, floor-at-doc_limit, provenance lineage, cross-repo topic wiring.

Reranking is skipped byte-identically when no reranker role is wired.
Requires the companion trustgraph-templates change wiring the reranker
topics into the document-rag flow (mirrors #279 for GraphRAG).
2026-07-02 09:50:13 +01:00
cybermaggedon
f18d48dc39
fix: simplify dashscope variant and route API calls through variants (#1012)
Replace the client.post()/httpx bypass with standard SDK extra_body,
confirmed working against DashScope. Make DashScope the base variant
with Qwen as a subclass alias. Route all API calls through variant
create_completion/create_completion_stream methods.
2026-07-02 09:12:55 +01:00
cybermaggedon
6887076ce0
feat: add dashscope variant for Alibaba Cloud DashScope API (#1010)
DashScope uses enable_thinking as a top-level parameter rather than
inside extra_body as the Qwen docs suggest.
2026-07-01 16:50:47 +01:00
cybermaggedon
55e2a2a3ce
feat: add guided macOS installer and developer install guide (#1003)
Interactive bash installer (install_trustgraph.sh) that detects hardware,
recommends an LLM mode (OpenAI or Ollama), installs missing prerequisites
via Homebrew, sets up a Python venv, runs the test suite, generates a
deployment via npx @trustgraph/config, starts the Docker Compose stack,
health-checks the API gateway, and opens the Workbench UI.

Includes README.dev-install.md with usage documentation covering CLI
options, environment variables, LLM mode selection, non-interactive/CI
usage, uninstall, and troubleshooting. Currently macOS only.
2026-07-01 16:50:14 +01:00
cybermaggedon
11ca7c89c4
feat: add GLM (Zhipu AI) variant for OpenAI processor (#1009) 2026-07-01 16:20:43 +01:00
cybermaggedon
656ca430b9
fix: wire variant into text-completion integration test mocks (#1008)
Tests using MagicMock processors need the variant, thinking mode,
and _build_kwargs/_extract_content methods bound to work with the
new variant-based API kwargs construction.
2026-07-01 15:40:23 +01:00
cybermaggedon
f20b50cfb2
feat: add API variant profiles and thinking support to OpenAI processor (#1007)
Add a --variant flag (openai, deepseek, qwen, mistral, llama) that
encapsulates provider-specific API differences: output token parameter
names, thinking/reasoning toggles, temperature rules, and thinking
output extraction. Add --thinking flag (off, low, medium, high) to
control reasoning effort.
2026-07-01 14:48:32 +01:00
Jack Colquitt
04c5921687
Fix Discord link in README (#1006)
Updated Discord link in README.md
2026-06-30 19:39:33 -07:00
cybermaggedon
01cc8dbc64
feat: replace LLM edge scoring with cross-encoder reranker in GraphRAG (#1005)
Replace the three-prompt LLM scoring pipeline (kg-edge-scoring,
kg-edge-reasoning, kg-edge-selection) with a cross-encoder reranker
service backed by FlashRank. The new hop_and_filter() method performs
iterative graph traversal with semantic scoring at each hop, replacing
the previous follow_edges/get_subgraph approach.

- Add reranker service (trustgraph-base client/service, FlashRank processor)
- Add gateway dispatch for reranker via API and WebSocket
- Rewrite GraphRAG pipeline: hop_and_filter() with per-hop cross-encoder scoring
- Remove kg_prompt() and edge_score_limit from prompt client
- Update provenance: add tg:EdgeSelection type, tg:concept, tg:score predicates
- Update CLIs (tg-invoke-graph-rag, tg-show-explain-trace) for new metadata
- Add tg-invoke-reranker CLI tool
- Add tech spec and UX developer guidance
- Update all unit and integration tests
2026-06-30 14:36:37 +01:00
corvus-0x
1aa9549912
feat: make bootstrapper initialiser timeouts configurable (#999)
* feat: make bootstrapper initialiser timeouts configurable

DefaultFlowStart and WorkspaceInit hardcoded the request timeouts for
their flow-svc and IAM calls, leaving operators no way to tune them for
high-latency environments (#874).

Expose them as constructor parameters threaded through the existing
initialiser `params:` mechanism, defaulting to the current values so
behaviour is unchanged unless explicitly overridden:

- DefaultFlowStart: list_timeout=10 (list-flows), start_timeout=30 (start-flow)
- WorkspaceInit: iam_timeout=10 (create-workspace)

Add unit tests for the defaults, override storage, and that configured
values reach the underlying request calls.

* test: mark async bootstrap test with @pytest.mark.asyncio

Addresses review feedback on PR #999: add the explicit
@pytest.mark.asyncio decorator to test_run_forwards_configured_timeouts
so it does not rely on asyncio_mode=auto and stays consistent with the
rest of the suite.
2026-06-30 09:37:22 +01:00
cybermaggedon
5cb4f83afa
fix: list-my-workspaces permissions were broken (#1002)
list-my-workspaces has AUTHENTICATED scope, so anyone is permitted
to run the operation.  No specific permission grant is needed.
2026-06-29 09:13:05 +01:00
cybermaggedon
0a828379be
feat: global usernames and rename workspace to default_workspace (#1001)
Users are global entities, not scoped to workspaces. This change:

Track A — Global usernames:
- Change iam_users_by_username to PRIMARY KEY (username), removing
  workspace from the lookup key
- Login looks up username globally, no workspace required
- Username uniqueness is enforced globally, not per-workspace
- Login -w now overrides the JWT workspace (session workspace)
  rather than selecting which user registry to search

Track B — Rename workspace to default_workspace:
- UserRecord.workspace → UserRecord.default_workspace
- Identity.workspace → Identity.default_workspace
- JWT claim "workspace" → "default_workspace"
- IamResponse.resolved_workspace → resolved_default_workspace
- WebSocket auth-ok frame field → default_workspace
- Socket clients read default_workspace from auth-ok
- _user_record_to_dict wire key → default_workspace
- CLI help text and output updated throughout
- Test files updated for renamed fields
2026-06-25 16:34:31 +01:00
cybermaggedon
16f8cfd972
fix: use envelope workspace for mux authorisation, not inner request body (#1000)
The mux was extracting the authorisation resource workspace from the
inner request body via registry extractors. But workspace-scoped
services (config, flow, librarian, etc.) receive workspace from the
queue identity, not the message body — the inner workspace field is
a dead field that no service handler reads.

This caused access-denied errors when the inner body's workspace
(e.g. CLI default "default") disagreed with the caller's assigned
workspace, even though the envelope workspace was correct.

Fix: resolve workspace from the envelope only. Split the non-flow
authorisation path by resource level — WORKSPACE ops use the envelope
workspace directly; SYSTEM ops (IAM) still use registry extractors
since they legitimately read operation-specific body fields.
2026-06-25 13:44:57 +01:00
Cyber MacGeddon
a3df4f62bb Merge branch 'master' into release/v2.6 2026-06-22 21:20:29 +01:00
cybermaggedon
09b8a1d347
feat: fine-grained capabilities and enterprise IAM schema extensions (#996)
Split coarse gateway capabilities into fine-grained variants to
support per-operation access control in the enterprise IAM regime.
Add additive schema fields for enterprise group and grant management.

Capability split (gateway registry):
- graph:read -> triples:read, sparql:read, graph-rag:read,
  graph-embeddings:read
- graph:write -> triples:write, graph-embeddings:write,
  entity-contexts:write
- documents:read -> documents:read, document-rag:read,
  document-embeddings:read, entity-contexts:read
- documents:write -> documents:write, document-embeddings:write
- rows:read -> rows:read, nlp-query:read, structured-query:read,
  row-embeddings:read

OSS role definitions expanded to include all new fine-grained
capability names — no behavioral change for OSS deployments.

Schema additions (IamRequest):
- group_id, member_type, member_id for group membership operations
- group (GroupInput), grant (GrantInput) for create/update payloads
- Decoder now handles capability, resource_json, parameters_json,
  authorise_checks (previously missing from translator)

Schema additions (IamResponse):
- group_json, groups_json, members_json, grants_json,
  effective_permissions_json for enterprise operation responses
- Encoder now emits authorise decision fields

Gateway registry:
- 16 enterprise IAM operations registered (create-group,
  add-group-member, add-user-grant, etc.) under iam:admin capability
2026-06-22 20:23:34 +01:00
Jack Colquitt
fa264ded46
Update section titles for Holonic Context Graph (#995) 2026-06-18 19:56:44 -07:00
Jack Colquitt
cae931409a
Update TrustGraph description in README (#994)
Clarified the description of TrustGraph's capabilities and API integrations.
2026-06-18 19:46:25 -07:00