~bigbes/sr-ht-spec

ref: 0879325b6c7e7d74454ecff0196b8d5ecc12f1ea sr-ht-spec/core/errors.go -rw-r--r-- 4.2 KiB
0879325b — bigbes docs: the empty-space-list polarity is retracted, not just documented 27 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Package core holds the pure domain logic of spec.sr.ht: owner and space name
// validation, safe document paths, the globally-unique document ID grammar, the
// frontmatter schema contract, `.spec.yml` space policy, the proposal state
// machine and branch naming, and [SpaceFilter] — what a project resolves to and
// what a search is scoped by, which is here rather than in either of them
// because it is the one thing they must agree about.
//
// It depends on nothing but the standard library and gopkg.in/yaml.v3, never
// touches the network or the filesystem, and knows nothing about git, Postgres
// or HTTP. Dependency direction is strictly downward: gitx, db, service, api and
// web import core; core imports none of them. That is what keeps the three
// agent-facing surfaces (REST, MCP, GraphQL) behaviourally identical — they
// share these rules rather than each re-deriving them.
package core

import "errors"

// Sentinel errors, one per failure class. Callers compare with errors.Is;
// wrapping with %w adds the offending value without losing the class, which is
// what lets the API layer map a failure to a status code (422 for a schema
// violation, 400 for a malformed name) without string matching.
var (
	// ErrInvalidName is returned for a malformed owner or space name.
	ErrInvalidName = errors.New("invalid name")

	// ErrReservedName is returned for a name that is well-formed but not the
	// caller's to claim. The one instance today is the meta-project: it is an
	// address that resolves to a filter excluding nothing, so a stored project
	// of that name could only shadow it.
	ErrReservedName = errors.New("reserved name")

	// ErrInvalidPath is returned for a path that is not a safe relative path
	// inside a space: absolute, traversing, or carrying bytes that would be
	// unsafe in a git tree or misleading in the review UI.
	ErrInvalidPath = errors.New("invalid path")

	// ErrInvalidDocID is returned for a document ID that does not match the
	// PREFIX-DIGITS grammar. IDs are globally unique and are the anchor for
	// cross-space links, comments and staleness checks, so shape is enforced
	// at every door.
	ErrInvalidDocID = errors.New("invalid document id")

	// ErrMalformedFrontmatter marks a document whose YAML frontmatter block is
	// missing, unterminated, not a mapping, or not parseable. It is distinct
	// from ErrMissingField: this is "cannot read", not "read but incomplete".
	ErrMalformedFrontmatter = errors.New("malformed frontmatter")

	// ErrMissingField marks frontmatter that parsed but omits a key the space's
	// schema requires. This is the 422 an agent gets for forgetting `status:`.
	ErrMissingField = errors.New("missing required frontmatter field")

	// ErrInvalidStatus is returned for a `status:` value outside the allowed
	// enum. Note "approved" is deliberately not a status — approval is a
	// property of the branch a document is reachable from, never of authored
	// metadata.
	ErrInvalidStatus = errors.New("invalid status")

	// ErrInvalidPolicy is returned for a `.spec.yml` that parses as YAML but
	// does not describe a usable policy.
	ErrInvalidPolicy = errors.New("invalid .spec.yml policy")

	// ErrInvalidPattern is returned for a malformed auto_merge path pattern.
	// A pattern that silently matches nothing would quietly turn the bimodal
	// cadence back into "everything waits for a human", so it is rejected.
	ErrInvalidPattern = errors.New("invalid path pattern")

	// ErrInvalidState is returned for a proposal state string outside the
	// open/merged/rejected set, typically read back from Postgres.
	ErrInvalidState = errors.New("invalid proposal state")

	// ErrInvalidTransition is returned for a proposal state change the machine
	// does not allow, such as re-merging an already rejected proposal.
	ErrInvalidTransition = errors.New("invalid proposal state transition")

	// ErrInvalidApproval is returned for an approval kind outside human/policy.
	ErrInvalidApproval = errors.New("invalid approval kind")

	// ErrInvalidProposalID is returned for a proposal id that cannot name a
	// proposal: ids are Postgres sequence values starting at 1, so anything
	// else is an unwritten row or an unset field rather than a proposal.
	ErrInvalidProposalID = errors.New("invalid proposal id")
)