Documentation
¶
Overview ¶
Package tracker mounts the Hanzo Cloud /v1/tracker/* surface: a native-Go, per-org issue tracker (projects + issues) on SQLite. It is the durable replacement for the Huly/Svelte hanzo.team tracker, whose upstream each-block reactive-batching render race left issue lists rendering zero rows. Native @hanzo/gui over this one store sidesteps that entire class of bug: the rows come back as plain JSON and render deterministically.
Tenant isolation is enforced SERVER-SIDE on every request: the org is principal.Tenant(c) — the value SanitizeIdentity minted from the VALIDATED bearer owner claim (HIP-0026) — and NEVER a client-supplied header. Every store query filters WHERE org=?, so one tenant can never read or mutate another's projects or issues.
Surface (all org-scoped; /v1 only):
POST /v1/tracker/projects create a project -> Project (201) GET /v1/tracker/projects list projects -> [Project] GET /v1/tracker/projects/:key project detail -> Project PATCH /v1/tracker/projects/:key update a project -> Project DELETE /v1/tracker/projects/:key delete a project (+ issues) POST /v1/tracker/projects/:key/issues create an issue -> Issue (201) GET /v1/tracker/projects/:key/issues[?status=] list issues (board/list) -> [Issue] GET /v1/tracker/projects/:key/issues/:num issue detail -> Issue PATCH /v1/tracker/projects/:key/issues/:num update an issue -> Issue DELETE /v1/tracker/projects/:key/issues/:num delete an issue
Order 129: binds /v1/tracker/* before the AI subsystem's /v1/* catch-all (150). serve.go auto-registers GET /v1/tracker/health.
Index ¶
- func Mount(app *zip.App, deps cloud.Deps) error
- func Shutdown() error
- type Issue
- type Project
- type Store
- func (s *Store) Close() error
- func (s *Store) CreateIssue(ctx context.Context, i Issue) (Issue, error)
- func (s *Store) CreateProject(ctx context.Context, p Project) error
- func (s *Store) DeleteIssue(ctx context.Context, org, projectID string, number int) (bool, error)
- func (s *Store) DeleteProject(ctx context.Context, org, key string) (bool, error)
- func (s *Store) GetIssue(ctx context.Context, org, projectID string, number int) (Issue, error)
- func (s *Store) GetProject(ctx context.Context, org, key string) (Project, error)
- func (s *Store) ListIssues(ctx context.Context, org, projectID, status string) ([]Issue, error)
- func (s *Store) ListProjects(ctx context.Context, org string) ([]Project, error)
- func (s *Store) UpdateIssue(ctx context.Context, i Issue) error
- func (s *Store) UpdateProject(ctx context.Context, p Project) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Issue ¶
type Issue struct {
ID string
ProjectID string
Org string
Number int
Title string
Description string
Status string
Priority string
Assignee string
Labels string
CreatedAt int64
UpdatedAt int64
}
Issue is one work item inside a Project. Number is monotonic PER PROJECT (KEY-1, KEY-2, …), allocated under the single-writer transaction in CreateIssue so it never races. Status is the board column; Labels is a comma-joined tag string (split at the HTTP boundary).
type Project ¶
type Project struct {
ID string
Org string
Key string
Name string
Description string
CreatedAt int64
UpdatedAt int64
}
Project is an org-scoped issue tracker project (a Linear "team"). Its Key is the org-unique, uppercase handle that both routes the URL (/v1/tracker/ projects/:key) AND prefixes every issue identifier (KEY-<number>). Tenant isolation is the org column, filtered on every query.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is one (org, project)'s tracker database — ONE SQLite file per project at {DataDir}/orgs/{orgSlug}/projects/{projectSlug}/tracker.db (opened via cloud.TenantDB). tracker is project-scoped: the physical boundary is the IAM project, with the org column retained as defense-in-depth. MaxOpenConns(1) serializes writes against the file lock (and makes the CreateIssue number allocation a safe read-modify-write inside one transaction).
func (*Store) CreateIssue ¶
CreateIssue allocates the next per-project number and inserts the issue in ONE transaction. The transaction holds the single pool connection for its whole duration, so the MAX(number)+1 read and the INSERT are serialized against any concurrent create — the number can never be handed out twice.
func (*Store) CreateProject ¶
CreateProject inserts one project. A UNIQUE(org,key) violation surfaces as errConflict.
func (*Store) DeleteIssue ¶
DeleteIssue removes one issue scoped to (org, project, number). Reports whether a row was deleted.
func (*Store) DeleteProject ¶
DeleteProject removes a project and all its issues in one transaction. Reports whether a project row was deleted.
func (*Store) GetIssue ¶
GetIssue returns one issue scoped to (org, project, number) or errNotFound.
func (*Store) GetProject ¶
GetProject returns the project for (org,key) or errNotFound.
func (*Store) ListIssues ¶
ListIssues returns issues for a project, optionally filtered to one status (empty status = all). Ordered by status then number so a status-grouped view renders deterministically and a single-column board reads oldest-first.
func (*Store) ListProjects ¶
ListProjects returns every project for org, most-recently-updated first.
func (*Store) UpdateIssue ¶
UpdateIssue overwrites the mutable fields of an issue scoped to (org, project, number). id+project_id+org+number+created_at are immutable.