team

package
v1.801.473 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 50 Imported by: 0

Documentation

Overview

Package team is your org's shared workspace: documents edited together, files, seats, and agents as teammates.

It is Hanzo Team: IAM sign-in and workspace selection, the transactor WebSocket a workspace's documents ride, collaborative editing on /collaborator, per-workspace files, the wallet page with its plan + seats, and the org's agents projected in as bot members.

The published surface is the typed ops themselves (plugin/team/openapi.json) — there is no second route table here to drift out of date.

TENANT ISOLATION. The org (tenant key) is NEVER a client-supplied header on any data path:

  • transactor: org = the `extra.org` claim of the HS256 workspace token in the :token path segment, minted by selectWorkspace and VERIFIED (token.Decode verify=true) against SERVER_SECRET before the WebSocket upgrade. Every docs SQLite file lives at {DataDir}/team/workspaces/orgs/<org>/projects/<ws>/docs.db.
  • account RPC: org = the `extra.org` claim of the HS256 session token in the bearer/cookie, likewise VERIFIED. Every account-store query filters by org; selectWorkspace resolves the workspace scoped to (org, slug) so a foreign tenant's slug is unresolvable.
  • bots read routes: org = principal.Org(c) — the value the identity middleware minted from the VALIDATED IAM owner claim (HIP-0026) — and never a client X-Org-Id.

The session-token org is itself minted from the VERIFIED IAM `owner` claim at the OAuth callback, so the chain IAM owner → session token → workspace token → docs path is signed end-to-end and a client can forge none of it.

Order 138: binds /v1/team/* before the AI subsystem's /v1/* catch-all (150).

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalid = errors.New("zap: invalid frame")

ErrInvalid is returned for a malformed ZAP frame.

Functions

func Apply

func Apply(org, workspace, account string, txes ...map[string]any)

Apply ingests platform CUD txes into a workspace's store exactly as a live client would (same applyTx path, same triggers) and broadcasts the applied txes to every open session of that workspace (realtime). account is the attribution used for triggers/PersonSpace ownership. No-op until Mount runs.

func Encode

func Encode(e Envelope) []byte

Encode serializes e into a single ZAP message.

func MemberTxes

func MemberTxes(m Member, exists bool) []map[string]any

MemberTxes builds the txes to project a member. When the Person already EXISTS it only UPDATES the mirror-owned name + refreshes the Employee mixin (which merges, never replaces) — so avatar/city/birthday/profile and any SPA-set mixin survive. On first projection it creates the Person + the hanzo social identity. The Employee mixin (active) is what puts the member in the Team list and fires the PersonSpace trigger.

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount wires the /v1/team/* surface onto app per HIP-0106. It opens the two SQLite stores under {DataDir}/team, wires the account API, the transactor WebSocket and the bots read routes, and publishes the transactor singleton so the in-process projection path can write into the workspace store.

The uniform /v1/team/health liveness route is provided by the compose root (serve.go registers GET /v1/<name>/health for every enabled subsystem BEFORE MountAll, HIP-0106) — the SAME contract clients/tracker, clients/crm and clients/agents rely on. Mount does NOT re-register it (a second identical route is dead — Fiber matches the first-registered — and violates one-way).

func PersonRef

func PersonRef(userID string) string

PersonRef is the deterministic Person _id for a member account — stable so re-syncs upsert in place (never duplicate a member).

func Shutdown

func Shutdown() error

Shutdown releases the team stores (account DB + every cached per-workspace docs handle). Idempotent — safe to call when nothing is mounted.

Types

type AgentRunner

type AgentRunner func(ctx context.Context, org, userSub, agentID, input string) (string, error)

AgentRunner runs agent `agentID` for `org` on behalf of `userSub` with `input` and returns the model's text output. It is injected in Mount (only when the feature is enabled) as an adapter over agents.RunOnBehalf — the ONE in-process run path (billed, metered, recorded) — so clients/team never speaks clients/agents' concrete run types and the responder is testable with a fake.

type Bot

type Bot struct {
	ID     string
	Name   string
	Active bool
}

Bot is the minimal projection of an org agent the roster reconcile needs. It is the seam that keeps clients/team decoupled from clients/agents' concrete Agent type — team names only what it projects (id, name, active).

type BotLister

type BotLister func(ctx context.Context, org string) ([]Bot, error)

BotLister sources an org's bots (the canonical in-process agents). It is injected in Mount as an adapter over agents.ListForOrg — the ONE in-process seam, replacing the removed IAM-SA HTTP enumeration. org is always a VERIFIED tenant (the transactor token's extra.org), never a client header.

type Envelope

type Envelope struct {
	ID      uint32
	Kind    Kind
	Method  string
	Payload []byte // JSON
}

Envelope is one decoded ZAP frame.

func Decode

func Decode(data []byte) (Envelope, error)

Decode parses a ZAP message into an Envelope. The payload is copied out so the caller may retain it past the frame's lifetime.

type Kind

type Kind uint8

Kind discriminates the three frame directions on the wire.

const (
	KindRequest  Kind = 0 // client → server call
	KindResponse Kind = 1 // server → client reply (correlated by ID)
	KindPush     Kind = 2 // server → client broadcast (ID is ignored)
)

type LoginInfo

type LoginInfo struct {
	Account  string `json:"account"`
	Name     string `json:"name,omitempty"`
	SocialID string `json:"socialId,omitempty"`
	Token    string `json:"token,omitempty"`
}

LoginInfo is the base login response. token overrides any prior token.

type Member

type Member struct {
	UserID string // account uuid (also the Person.personUuid + social key)
	Name   string // display name
	Role   string // owner/admin/member — surfaced on the Employee mixin
	IsBot  bool
	Active bool // Employee.active — drives Team/Employee-list membership
}

Member is the projection of a team member (human or bot) rendered as a Person + Employee in the SPA directory.

type ProviderInfo

type ProviderInfo struct {
	// Name is the provider id, and it is the value that goes back in the URL to
	// start a login: GET /v1/team/account/auth/{provider}. This deployment
	// surfaces exactly one, "openid" — the hanzo.id door.
	Name string `json:"name"`
	// DisplayName is the human label for the sign-in button; this deployment
	// sends "Hanzo". Omitted from the body when empty.
	DisplayName string `json:"displayName,omitempty"`
}

ProviderInfo is one entry of GET /providers.

type RegionInfo

type RegionInfo struct {
	Region string `json:"region"`
	Name   string `json:"name"`
}

RegionInfo is one entry of getRegionInfo.

type Role

type Role = string

Role is the platform AccountRole. Stored on members.role (lowercased) and surfaced uppercased in WorkspaceLoginInfo.role.

type SocialID

type SocialID struct {
	ID           string `json:"_id"`
	Type         string `json:"type"`
	Value        string `json:"value"`
	Key          string `json:"key"`
	DisplayValue string `json:"displayValue,omitempty"`
	VerifiedOn   int64  `json:"verifiedOn,omitempty"`
	IsDeleted    bool   `json:"isDeleted,omitempty"`
}

SocialID is one entry of getSocialIds. The workbench connect flow runs pickPrimarySocialId over these: it needs at least one non-deleted id and prefers type "hanzo".

type Status

type Status struct {
	Severity string         `json:"severity"`
	Code     string         `json:"code"`
	Params   map[string]any `json:"params"`
}

Status is the platform PlatformError payload sent as {"error": Status}. Severity is the platform's STRING enum ("OK"/"INFO"/"WARNING"/"ERROR") — the SPA compares it against those literals, so a numeric severity matches nothing.

type WorkspaceInfo

type WorkspaceInfo struct {
	UUID   string `json:"uuid"`
	Name   string `json:"name"`
	URL    string `json:"url"`
	DataID string `json:"dataId,omitempty"`
	// Org is the workspace's owning IAM tenant. getUserWorkspaces unions a user's
	// workspaces across every org they belong to, so the client switcher groups by
	// this field (a user in two orgs sees both orgs' workspaces, each tagged).
	Org          string `json:"org,omitempty"`
	Region       string `json:"region"`
	Mode         string `json:"mode"`
	VersionMajor int    `json:"versionMajor"`
	VersionMinor int    `json:"versionMinor"`
	VersionPatch int    `json:"versionPatch"`
	LastVisit    int64  `json:"lastVisit,omitempty"`
	IsDisabled   bool   `json:"isDisabled"`
	CreatedOn    int64  `json:"createdOn,omitempty"`
}

WorkspaceInfo is one entry of getUserWorkspaces. The version triple is the Team MODEL version (the SAME source the transactor reports as serverVersion).

type WorkspaceLoginInfo

type WorkspaceLoginInfo struct {
	LoginInfo
	Workspace        string `json:"workspace"`
	WorkspaceDataID  string `json:"workspaceDataId,omitempty"`
	WorkspaceURL     string `json:"workspaceUrl"`
	Endpoint         string `json:"endpoint"`
	Role             Role   `json:"role"`
	AllowGuestSignUp bool   `json:"allowGuestSignUp,omitempty"`
}

WorkspaceLoginInfo extends LoginInfo — returned by selectWorkspace. token is the per-workspace JWT; endpoint is the transactor wss:// base the client connects to.

Directories

Path Synopsis
Package token mints and verifies the HS256 JWTs that the team SPA, the /v1/team/account API and the /v1/team/transactor data plane all share.
Package token mints and verifies the HS256 JWTs that the team SPA, the /v1/team/account API and the /v1/team/transactor data plane all share.
Package wallet embeds the built hanzo.team usage/wallet page — a SMALL @hanzo/ui@8 React static export (app/, Vite) — into the cloud binary, the same one-binary/one-origin precedent as the console (webui.go) and the tasks SPA (clients/tasks/ui).
Package wallet embeds the built hanzo.team usage/wallet page — a SMALL @hanzo/ui@8 React static export (app/, Vite) — into the cloud binary, the same one-binary/one-origin precedent as the console (webui.go) and the tasks SPA (clients/tasks/ui).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL