v0.5.0 131f96f

bootstrap.go RawHistoryFolder

1package auth
2
3import (
4	"encoding/binary"
5	"io"
6
7	"github.com/bnema/neferafk/internal/ports"
8)
9
10// The bootstrap record is the first and only non-frame traffic on the worker's
11// stdin pipe (fd 3), written by the visual process once per lock:
12//
13//	"NAB1" | u32 length | generation u64 | 3 x (u32 length | bytes)
14//
15// where the byte strings are PINSource, PINReference and EnvPIN.
16const bootstrapMax = 8 + 3*4 + 16 + ports.AuthMaxMetadata + ports.AuthMaxSecret
17
18// WriteBootstrap encodes b; it wipes its encoded copy but not b.EnvPIN.
19func WriteBootstrap(w io.Writer, b ports.AuthBootstrap) error {
20	if b.Generation == 0 || len(b.PINSource) > 16 || len(b.PINReference) > ports.AuthMaxMetadata || len(b.EnvPIN) > ports.AuthMaxSecret {
21		return ErrProtocol
22	}
23	p := make([]byte, 8, bootstrapMax+8)
24	binary.BigEndian.PutUint64(p, b.Generation)
25	for _, f := range [][]byte{[]byte(b.PINSource), []byte(b.PINReference), b.EnvPIN} {
26		p = binary.BigEndian.AppendUint32(p, uint32(len(f)))
27		p = append(p, f...)
28	}
29	out := append(append(make([]byte, 0, 8+len(p)), "NAB1"...), 0, 0, 0, 0)
30	binary.BigEndian.PutUint32(out[4:], uint32(len(p)))
31	out = append(out, p...)
32	clear(p)
33	defer clear(out)
34	return writeAll(w, out)
35}
36
37// ReadBootstrap decodes one record. The caller owns and wipes EnvPIN.
38func ReadBootstrap(r io.Reader) (ports.AuthBootstrap, error) {
39	var h [8]byte
40	if _, err := io.ReadFull(r, h[:]); err != nil {
41		return ports.AuthBootstrap{}, err
42	}
43	n := binary.BigEndian.Uint32(h[4:])
44	if string(h[:4]) != "NAB1" || n < 8+12 || n > bootstrapMax {
45		return ports.AuthBootstrap{}, ErrProtocol
46	}
47	p := make([]byte, n)
48	defer clear(p)
49	if _, err := io.ReadFull(r, p); err != nil {
50		return ports.AuthBootstrap{}, err
51	}
52	b := ports.AuthBootstrap{Generation: binary.BigEndian.Uint64(p)}
53	rest := p[8:]
54	var f [3][]byte
55	for i := range f {
56		if len(rest) < 4 {
57			return ports.AuthBootstrap{}, ErrProtocol
58		}
59		l := binary.BigEndian.Uint32(rest)
60		if uint64(l) > uint64(len(rest)-4) {
61			return ports.AuthBootstrap{}, ErrProtocol
62		}
63		f[i], rest = rest[4:4+l], rest[4+l:]
64	}
65	if b.Generation == 0 || len(rest) != 0 || len(f[0]) > 16 || len(f[1]) > ports.AuthMaxMetadata || len(f[2]) > ports.AuthMaxSecret {
66		return ports.AuthBootstrap{}, ErrProtocol
67	}
68	b.PINSource, b.PINReference = ports.PINSource(f[0]), string(f[1])
69	if len(f[2]) > 0 {
70		b.EnvPIN = append([]byte(nil), f[2]...)
71	}
72	return b, nil
73}

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 2

Tags 9

↑↓ moveenter openesc close