Package Information
Available Nodes
Documentation generating…
Documentation
n8n-nodes-zuga-hivemind
An n8n community node for Zuga Hivemind: file/list/update tickets, read/write docs,
read the goal tree, send messages, and search shared memory — plus a polling trigger
for new tickets and messages.
⚠️ Multi-tenant isolation — read before giving this to a client
Hivemind's tenant isolation exists in code but ships DISABLED.
src/hivemind/tenancy.py implements database-per-tenant: a request resolves to one
tenant's SQLite file, so another tenant's rows are not merely filtered out — they are
not present. It fails closed (raises rather than falling back to the default database).
That design is sound.
But it is gated behind HIVEMIND_TENANCY_ENABLED=1, and the module's own docstring
says "SHIPPED DISABLED". With the flag unset:
- every valid API key can read and write every ticket, doc, goal and channel;
scopeson an account is documented inserver.pyas "NOT an access-control layer";- two clients pointed at the same server would see each other's data.
So the credential this node holds is a teammate key, not a per-client key. Before
this connector is handed to an external client:
- Turn on
HIVEMIND_TENANCY_ENABLED=1on the server the client will hit. - Verify a second tenant's key cannot read the first tenant's tickets — by trying it,
not by reading the code.
Until then this is an internal-team connector.
What it talks to
Every resource/operation maps to exactly one hivemind HTTP route that accepts a
teammate X-API-Key. The /bridge/* and /search/* routes are gated by hivemind's
separate service admin token and are deliberately out of scope.
| Resource | Operations | Routes |
|---|---|---|
| Ticket | file / list / update | POST /report, GET /tickets, POST /ticket/update |
| Doc | read / write / list | GET /memory/doc, POST /memory/doc, GET /dashboard/api/docs |
| Goal | getTree / addNote | GET /dashboard/api/goals, POST /goal/note |
| Message | send / readChannel / readInbox | POST /dashboard/api/send, GET /dashboard/api/channel, GET /dashboard/api/inbox |
| Memory | search | POST /memory/retrieve |
Auth
Reuses the existing per-teammate key minted server-side via POST /register
(admin-only — see the mint-hivemind-key skill). The key rides as the X-API-Key
header, the same header hivemind's dashboard and MCP clients use. This credential
holds a key; it does not mint or manage them.
The credential test calls GET /dashboard/api/me rather than /health, because/health needs no key and would "pass" against any URL returning 200. /me proves
both that the key is valid and that the base URL is actually a hivemind server.
Trigger model — polling, by necessity
Hivemind emits no outbound webhooks. The only webhook it exposes
(POST /webhook/github, HMAC-signed) is an inbound listener, not an event bus.
So New Ticket / New Message poll and compare against the highest id seen on the
previous run, stored in the node's workflow static data.
On first activation the trigger records a baseline and emits nothing — otherwise
every ticket that already existed would fire the moment you switch it on.
Build
npm install
npm run build # tsc -> dist/, then copies the icon
dist/ is gitignored: build output is not source.
Source recovery note (2026-08-16)
This package previously existed on disk as dist/ and node_modules/ only — nopackage.json, no .ts, on either machine, and nothing in git history. A connector
that cannot be rebuilt cannot be shipped or maintained, so the source in src/ was
recovered from the compiled output.
The recovery was verified rather than assumed: the recovered source compiles clean
under strict: true, and its emitted JavaScript is byte-identical to the original
tested dist/ for all four files (modulo CRLF vs LF). What was lost at compile time
and had to be restored by hand: parameter/return type annotations, the this: IExecuteFunctions / this: IPollFunctions signatures, and interface declarations.