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+test on dev-linux-kvs). RFC tribus-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.