Foundation Tribus (cooperative-work primitive)
- Area: Foundation
- Path:
services/foundation/tribus - Kind: Go service (self-contained module; in-memory store, kdb-backed pending)
- Status: backend built + green (
go vet+build+teston dev-linux-kvs). RFCtribus-RFC-001. NOT yet LXC-deployed. In-progress: #001 (kdb apply), #006 (id/Mail wiring). - RFC:
meta/docs/stack/rfcs/tribus-RFC-001-foundations.kmd
Role in the stack
Koder Tribus is the Stack's cooperative-work primitive — Koder's open/self-hosted answer to the category of Claude Cowork, which a 2026-06-04 comparative found uncovered (KPCKodeAgents are all single-user-isolated). It owns the primitive, not a user-facing product (that would be a separate tribus-RFC-002).
The unit is a tribe: a shareable container with its own membership/ACL, decoupled from each member's home tenant, over which users share and interact with work, tasks, and files. It is deliberately called tribe and not "cowork space" — workspace is already load-bearing in the Stack (id-RFC-012 §2 = the B2B org account; multi-tenancy/contract.kmd workspace_id = governance boundary). "tribe" kills that collision.
Membership is tiered, not a fixed account type: T0 = cross-tenant Koder identities (individual + org member) by explicit grant; T1 = external email via invite→signup (becomes a real Koder identity) or anonymous share-link — respecting the sole-IdP rule (oauth-client-external-providers.kmd R1); T2 = federated guest without a Koder account = deferred owner decision.
The keystone is a carve-out from the cross-tenant=404 default: a tribe grants visibility by membership exactly like workspace_member, documented as the "Tribe-scoped sharing overlay" in multi-tenancy/contract.kmd (tests T13/T14).
Primary couplings
| Module | Direction | Why |
|---|---|---|
services/foundation/id |
consumes (JWKS) | Auth: engines/sdk/go/auth.JWKSValidator validates id access tokens |
engines/sdk/go/auth |
imports | Real JWT/JWKS validation (reuse-first; no local stub in prod) |
engines/sdk/go/obs |
imports | 3 signals: SetupOTLP + RED middleware + counters (observability-first) |
services/foundation/sync |
mirrors | Pattern source for the WS broker (presence fan-out) |
products/horizontal/drive |
mirrors | Pattern source for the share-link / ACL model |
services/foundation/id (RFC-013) |
consumes (future) | Invite→signup redemption hook (#006) |
| Drive / Board / Craft / KPC | consume (future) | Attach resources to a tribe via tribe_resource (#013) |
The module is self-contained (own go.mod, std-lib + gorilla/websocket + golang-jwt + golang.orgxcrypto + otel), importing the in-monorepo engines/sdk/go via a replace directive (requires Go ≥ 1.25.7 → build on dev-linux-kvs).
Surfaces (REST, :8097)
| Verb + path | Auth | Purpose |
|---|---|---|
POST /v1/tribes · GET /v1/tribes · GET /v1/tribes/joined |
bearer | create / list owned / list joined |
GET·PATCH·DELETE /v1/tribes/{id} · POST …/leave |
bearer | get / rename / delete / leave |
GET·POST /v1/tribes/{id}/members · PUT·DELETE …/members/{user_id} |
bearer | membership + role |
GET·POST /v1/tribes/{id}/links · DELETE …/links/{token} |
bearer | manage share-links |
GET /v1/links/{token} |
none | anon resolve (rate-limited, capped view) |
POST·GET /v1/tribes/{id}/resources · DELETE …/{rid} |
bearer | attach / list / detach work refs |
GET /v1/tribes/{id}/ws |
bearer | presence + activity stream (membership-gated) |
POST /v1/invites/redeem |
bearer (trusted) | bind an external-email invite to a Koder user |
GET /healthz · GET /readyz |
none | probes |
Invariant across every authenticated read: default-deny — a non-member gets 404, not 403; a non-manager member gets 403. Errors follow the JSON contract {error:{code,message}}.
Data model
koder_tribus.tribe (owner + title) · koder_tribus.tribe_member (grant: koder_user / invited / anyonewithlink × ownereditorcommenter/viewer) · koder_tribus.tribe_resource (kind ∈ drivefileboardcraftdoctasklink + ref). All gated by the RLS overlay above. Migrations 001_init.sql + 002_tribe_resource.sql.