detached 5f5b000

signatures.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package ports
4
5import (
6	"context"
7
8	"bnema.dev/ermite/internal/domain"
9)
10
11// CommitObjectReader reads raw commit objects (ADR 0030).
12type CommitObjectReader interface {
13	// ReadCommitObjects returns the raw content of each commit (without the
14	// "commit <size>\0" prefix), keyed by id. Ids that are missing, are not
15	// commits, or exceed domain.MaxCommitObjectBytes are left out of the map.
16	// The total size of the returned objects stays within
17	// domain.MaxCommitObjectsBytes: ids are read in order, and the first one
18	// that would exceed the budget ends the read, so it and the ids after it
19	// are left out (the caller leaves those commits unchecked). A cancelled
20	// ctx is returned as its error.
21	// domain.ErrNotFound when the repository has no directory.
22	ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error)
23}
24
25// KeyInspector parses public keys for the trusted key list.
26type KeyInspector interface {
27	// Inspect parses a public key of the given format and returns its ID
28	// (fingerprint) and its canonical text: the "<type> <base64>" part of an
29	// authorized_keys line for SSH (comment dropped), the armored public key
30	// for GPG (exactly one entity, private material refused). Any parse
31	// failure wraps domain.ErrInvalid.
32	Inspect(format domain.SignatureFormat, publicKey string) (id, canonical string, err error)
33}
34
35// SignatureVerifier checks one signature against a set of trusted keys. It
36// never errors: every failure is a status.
37type SignatureVerifier interface {
38	// Verify checks signature over payload, signed by committerEmail.
39	// signedAt is the committer date: the committer chooses it, and it is
40	// authenticated as part of the payload but is not a trusted timestamp.
41	// SSH ignores it, and so does GPG, which
42	// judges key and signature expiry at the signature creation time and
43	// revocation at the current time. keys are the trusted keys of the
44	// verifier's format. It returns Format, Status, Fingerprint, and
45	// KeyID/KeyTitle of the key that verified (even on email_mismatch).
46	Verify(payload, signature []byte, committerEmail string, signedAt int64, keys []domain.TrustedKey) domain.CommitVerification
47}
48
49// TrustedKeyStore keeps the trusted keys (ADR 0030). It does not bound their
50// number: the use case checks domain.MaxTrustedKeys.
51type TrustedKeyStore interface {
52	// ListTrustedKeys returns every stored key, oldest first.
53	ListTrustedKeys(ctx context.Context) ([]domain.TrustedKey, error)
54	// CreateTrustedKey stores a key; domain.ErrAlreadyExists if the ID is taken.
55	CreateTrustedKey(ctx context.Context, k domain.TrustedKey) error
56	// DeleteTrustedKey removes a key or returns domain.ErrNotFound.
57	DeleteTrustedKey(ctx context.Context, id string) error
58}
59
60// TrustedKeyService manages the trusted keys. *usecase.Signatures implements it.
61type TrustedKeyService interface {
62	// ListTrustedKeys lists the keys, the builtin instance key first. Any
63	// authenticated caller may.
64	ListTrustedKeys(ctx context.Context, p domain.Principal) ([]domain.TrustedKey, error)
65	// AddTrustedKey adds a key. Owner only.
66	AddTrustedKey(ctx context.Context, p domain.Principal, format domain.SignatureFormat, title, publicKey string, emails []string) (domain.TrustedKey, error)
67	// RemoveTrustedKey removes a key by ID. Owner only; the builtin key is
68	// refused with domain.ErrPreconditionFailed.
69	RemoveTrustedKey(ctx context.Context, p domain.Principal, id string) error
70}
71
72// CommitVerifier tells the signature state of commits the caller already read.
73// *usecase.Signatures implements it.
74type CommitVerifier interface {
75	// VerifyCommits returns one verification per commit, keyed by id. A
76	// commit that could not be read is left out (unchecked).
77	VerifyCommits(ctx context.Context, repo domain.RepoName, commits []domain.Commit) map[domain.ObjectID]domain.CommitVerification
78}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close