// Package service is spec.sr.ht's orchestration layer: the single seam that // REST, MCP, GraphQL and the web UI all call, and the only place where git, // Postgres and identity are allowed to meet. // // Dependency direction is strictly downward. This package imports core, gitx, // db and authn; nothing above it may touch gitx or db directly. That rule is // what keeps the three agent-facing surfaces behaviourally identical — they // share these functions rather than each re-deriving the rules. // // # What Phase 1 contains // // Reads, validation and repair. Concretely: // // - Wiring: [Config] and [New] assemble a [Service] from the shared // SourceHut config.ini, failing loudly at startup on a missing key rather // than deep inside the first request. // - Space lifecycle: [Service.CreateSpace], [Service.OpenSpace], // [Service.ListSpaces]. // - Reads: [Service.ReadDocument], [Service.ListDocuments], // [Service.Policy] — each resolving either the approved head or a pinned // revision through the same code path, because there is one storage tier // and no checkout. // - Push validation: [Service.ValidatePush], the function the `update` hook // calls over RPC before a ref moves. // - Repair: [Reconcile] and [Service.RunReconciler]. // // The write plane — propose, If-Match resolution, merge, auto-merge policy, // digest bookkeeping — is Phase 3 and is deliberately absent. // // # What Phase 2 adds here // // Projects: [Service.CreateProject], [Service.GetProject], // [Service.ListProjects], [Service.DeleteProject], // [Service.AddSpaceToProject], [Service.RemoveSpaceFromProject], // [Service.ProjectSpaces], [Service.ProjectsForSpace], and the read they exist // for, [Service.ResolveProject]. // // A project is pure metadata — a saved filter, not a container. It owns no // index and no storage: there is one global bleve index, and a project query is // that index restricted to the project's spaces ([SpaceFilter]). The // meta-project, "~owner/+everything", is the degenerate case — a filter that // excludes nothing ([EverythingFilter]) — and is deliberately not a row. // // # One storage tier // // Every read resolves a git revision and reads blobs. The approved head, a // pinned ?rev= and a proposal branch are the same call with a different // revision string; an empty revision means "the approved head", which is what // makes "reads default to the approved revision" a property of this layer // rather than of each caller. // // # Errors // // Callers above this layer must not need gitx or db to interpret a failure, so // every error that leaves this package satisfies one of the sentinels declared // here ([ErrNotFound], [ErrSpaceExists], [ErrPushRejected], ...) as well as the // lower-level class it came from. Multi-%w wrapping keeps both. package service