Documentation
¶
Overview ¶
connectors.go is the per-org app-connector control plane: OAuth into Slack / GitHub / Google, store the token in KMS (never plaintext, never logged), and sync external documents INTO the same per-org knowledge store + vector index as manual pages. A connector is a pure PRODUCER of framework documents (kb-source) — it creates them through framework.Ingest, so the SAME after_save indexing hook that serves manual pages indexes them. One knowledge store, many sources, one index.
SECURITY (the tenant + secret boundary):
- Every handler resolves its org from principal.Org (a validated principal), NEVER a client field. A caller can only ever connect/sync/disconnect its OWN org, and synced docs are written into that org's store only.
- The OAuth token is a RETRIEVABLE secret (it must be presented to the provider API), so it lives in KMS at a deterministic per-org path — never in the kb-connector document, never in a log line. The document holds only the KMS PATH (kms_ref) and non-secret connection metadata.
- The OAuth `state` is an HMAC over (org|provider|nonce|expiry) keyed by a server secret, so the callback re-derives the org from the STATE it signed — not from a client header and not from the provider — which defeats the login-CSRF / mix-up class (an attacker cannot bind their provider account to a victim org, nor steer a victim's callback to a foreign org).
Package kb declares the Hanzo Knowledge Base + unified AI memory model as DocType fixtures on the framework engine (clients/framework), and wires the ONE per-org vector-indexing path (index.go) that turns every knowledge document into retrievable org memory. It is the FOURTH app lane after cms/erp/help and the one that makes "a Notion-like wiki + agent memory" just another module on Base — no new Base, no new database.
Like cms/erp/help, the content model is fixtures: a wiki page IS a framework document (module "kb"), a memory IS a framework document, an ingested doc from a connector IS a framework document. CRUD, permissions, tenant isolation, and install are the framework's generic, already-live surface (/v1/framework/*) and the SAME generic @hanzo/ui DocType renderer that draws CMS and ERP.
UNLIKE the pure-fixture lanes, kb attaches BEHAVIOR (hooks.go): on every save of a knowledge document the after_save hook upserts its text to the org's vector namespace, and on trash it removes it. Human wiki + AI memory therefore share ONE per-org knowledge store, indexed once. kb ALSO mounts a thin retrieval + ingestion control-plane subsystem (subsystem.go, /v1/kb/*): semantic search (the RAG entry point an agent/chat calls) and app connectors (Slack/GitHub/ Google) that ingest external docs INTO the same store. Connectors are just producers of framework documents — they never fork the vector-write path.
Names are slug-style with a "kb-" prefix so they never collide with the CMS (Author/Media/Page/…), ERP (erp-*), or Help (hd-*) lanes and never carry a space the console's /cloud path filter would reject.
subsystem.go mounts the KB retrieval + ingestion control-plane at /v1/kb/*. It is the thin surface on top of the framework DocType store (CRUD lives at /v1/kb) and the vector index (index.go):
POST /v1/kb/search — the RAG entry point. An agent/chat resolves the org from its validated principal and asks "what does this org know about X"; the org's OWN vector namespace answers. This is how human wiki + AI memory become retrievable org knowledge for an agent.
GET /v1/kb/graph (graph.go) — the org's knowledge as a node/edge graph for a force-directed renderer: pages/memories/sources as nodes; the parent tree, wikilinks, and connector provenance as edges.
POST /v1/kb/import (import.go) — an Obsidian-importer-equivalent that ingests an Obsidian/Notion/Roam/Evernote export as a kb-page tree with links intact.
Connectors (connectors.go): per-org OAuth connections to Slack/GitHub/Google whose synced documents land in the SAME store + SAME index as manual pages.
Every handler resolves its tenant through principal.Org (the ONE boundary) and scopes strictly to that org — a caller can only ever search or connect its own knowledge.
sync.go implements OAuth code exchange and the per-provider document pull. Every pulled item is normalized to ONE shape (ingestDoc) and filed as a kb-source document via framework.Ingest — so the SAME after_save hook indexes it into the org's vector namespace, alongside manual pages and memories. This is the single ingestion path; providers differ only in how they LIST and FETCH, never in how they land in the store.
GitHub is implemented end-to-end (repo READMEs + issues via the REST API) as the proof. Slack and Google are wired to the SAME normalizer and OAuth lifecycle; their pull is scaffolded with an honest depth marker (they connect and record a connection, and the sync returns a clear "listing not yet implemented" rather than a fabricated ingest) so the depth is never overstated.
Index ¶
Constants ¶
const ( DTPage = "kb-page" // a Notion-like wiki page (nested via `parent`) DTMemory = "kb-memory" // a unit of agent/AI memory (note/fact/observation) DTSource = "kb-source" // a document ingested from an app connector or upload DTConnector = "kb-connector" // an app-connector connection (metadata only; token in KMS) DTLink = "kb-link" // a wikilink edge extracted from a kb-page body )
DocType names (slug, kb- prefixed). Exported so the hooks (hooks.go) and the retrieval subsystem (subsystem.go) reference the SAME identifiers as the fixtures — one source of truth for the doctype set.
const Module = "kb"
Module is the framework module tag every KB DocType carries. The console's KB surface is the generic DocType renderer scoped to this module (a page-tree sidebar over kb-page.parent + the Lexical editor over kb-page.body).
const RoleKBEditor = "KB Editor"
RoleKBEditor is the authoring role the KB DocTypes grant read/write/create/ delete. The org owner (System Manager, seeded trust-on-first-use) assigns it via /v1/framework/roles; a role-less member stays denied (secure by default). The engine seeds a System-Manager-only grant when perms are empty, so naming this role is an explicit widening, never a loosening.
Variables ¶
This section is empty.
Functions ¶
func DocTypes ¶
DocTypes returns the canonical KB + memory model. Masters have no cross-lane Links (kb runs standalone); kb-page's `parent` is a SELF Link (the framework resolves Link targets at document write, so a child may reference a parent defined in any order, and a page tree is just parent chains).
func Mount ¶
Mount wires the KB control-plane onto app per HIP-0106. CRUD + fixtures are the framework's surface; this adds only retrieval + connectors.
func SemanticReady ¶
func SemanticReady() bool
SemanticReady reports whether the vector leg is configured (an embedding client and a store endpoint). A deployment without one is DISABLED, which the surface reports distinctly from DEGRADED — "never provisioned" and "provisioned and broken" are different operational facts and must not share a status.
Types ¶
type Hit ¶
type Hit = hit
Hit is one semantic result. It is the retrieval hit shape verbatim (a type alias, not a copy) so the wire contract cannot drift between /v1/kb/search and /v1/search.
func Semantic ¶
func Semantic(ctx context.Context, r SemanticReq) ([]Hit, error)
Semantic runs the org-scoped vector leg. It returns an error (never a silent empty) when the store or the embedding gateway is unreachable, so the caller can report WHICH backend failed and why: the fail-empty behaviour that hid a five-day vector outage belongs to the surface's degradation contract, not here.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package evernote normalizes an Evernote .enex export into vault.Page documents.
|
Package evernote normalizes an Evernote .enex export into vault.Page documents. |
|
Package lexical builds a Lexical EditorState JSON string from block-structured content.
|
Package lexical builds a Lexical EditorState JSON string from block-structured content. |
|
export.go normalizes a Notion workspace EXPORT (the "Markdown & CSV" or "HTML" zip a user downloads) into vault.Page documents — distinct from notion.go, which shapes records from the live Notion API connector.
|
export.go normalizes a Notion workspace EXPORT (the "Markdown & CSV" or "HTML" zip a user downloads) into vault.Page documents — distinct from notion.go, which shapes records from the live Notion API connector. |
|
Package obsidian normalizes an Obsidian vault (a tree of markdown files) into vault.Page documents.
|
Package obsidian normalizes an Obsidian vault (a tree of markdown files) into vault.Page documents. |
|
Package roam normalizes a Roam Research JSON export into vault.Page documents.
|
Package roam normalizes a Roam Research JSON export into vault.Page documents. |
|
Package vault is the normalized model an importer produces: a set of pages with a parent tree and wikilinks preserved inline in the body.
|
Package vault is the normalized model an importer produces: a set of pages with a parent tree and wikilinks preserved inline in the body. |