Compare commits

..
3 Commits
Author SHA1 Message Date
emmatherock b73becb579 Store local credentials as structured JSON 2026-09-27 10:23:12 -03:00
emmatherock 6029850d08 Add Nix development shell 2026-09-27 10:23:03 -03:00
emmatherock 8de11e15a6 Rename repository guidance for coding agents 2026-09-27 10:22:52 -03:00
4 changed files with 46 additions and 5 deletions

No files matched your search

View File
File renamed without changes.
+15 -2
View File
@@ -22,6 +22,7 @@ import (
"crypto/sha256" "crypto/sha256"
"crypto/subtle" "crypto/subtle"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"log" "log"
"os" "os"
@@ -47,6 +48,11 @@ func tokenPath() string {
return "token.txt" return "token.txt"
} }
// tokenFile is token.txt's on-disk shape.
type tokenFile struct {
Token string `json:"token"`
}
func randomHex(n int) (string, error) { func randomHex(n int) (string, error) {
b := make([]byte, n) b := make([]byte, n)
if _, err := rand.Read(b); err != nil { if _, err := rand.Read(b); err != nil {
@@ -68,15 +74,22 @@ func resolveToken(cfg config) (token string, generated bool, err error) {
} }
path := tokenPath() path := tokenPath()
if data, rerr := os.ReadFile(path); rerr == nil { if data, rerr := os.ReadFile(path); rerr == nil {
if t := strings.TrimSpace(string(data)); t != "" { var tf tokenFile
if jerr := json.Unmarshal(data, &tf); jerr == nil {
if t := strings.TrimSpace(tf.Token); t != "" {
return t, false, nil return t, false, nil
} }
} }
}
t, gerr := randomHex(tokenBytes) t, gerr := randomHex(tokenBytes)
if gerr != nil { if gerr != nil {
return "", false, fmt.Errorf("couldn't generate a token: %w", gerr) return "", false, fmt.Errorf("couldn't generate a token: %w", gerr)
} }
if werr := os.WriteFile(path, []byte(t), 0600); werr != nil { blob, merr := json.MarshalIndent(tokenFile{Token: t}, "", " ")
if merr != nil {
return "", false, fmt.Errorf("couldn't encode token.txt: %w", merr)
}
if werr := os.WriteFile(path, blob, 0600); werr != nil {
return "", false, fmt.Errorf("couldn't save token.txt: %w", werr) return "", false, fmt.Errorf("couldn't save token.txt: %w", werr)
} }
return t, true, nil return t, true, nil
+17 -3
View File
@@ -16,6 +16,7 @@ package main
import ( import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"log" "log"
"os" "os"
@@ -316,16 +317,24 @@ partner = ""
// load a different save. With its own id, the hub keeps seeing the same // load a different save. With its own id, the hub keeps seeing the same
// partner even if they switch characters, reconnect, or restart the // partner even if they switch characters, reconnect, or restart the
// program. // program.
// clientIDFile is client-id.txt's on-disk shape.
type clientIDFile struct {
ID string `json:"id"`
}
func clientID() string { func clientID() string {
path := "client-id.txt" path := "client-id.txt"
if exe, err := os.Executable(); err == nil { if exe, err := os.Executable(); err == nil {
path = filepath.Join(filepath.Dir(exe), "client-id.txt") path = filepath.Join(filepath.Dir(exe), "client-id.txt")
} }
if data, err := os.ReadFile(path); err == nil { if data, err := os.ReadFile(path); err == nil {
if id := strings.TrimSpace(string(data)); id != "" { var f clientIDFile
if jerr := json.Unmarshal(data, &f); jerr == nil {
if id := strings.TrimSpace(f.ID); id != "" {
return id return id
} }
} }
}
var b [8]byte var b [8]byte
if _, err := rand.Read(b[:]); err != nil { if _, err := rand.Read(b[:]); err != nil {
// No randomness available: still return something stable for // No randomness available: still return something stable for
@@ -333,7 +342,12 @@ func clientID() string {
return fmt.Sprintf("pid-%d", os.Getpid()) return fmt.Sprintf("pid-%d", os.Getpid())
} }
id := hex.EncodeToString(b[:]) id := hex.EncodeToString(b[:])
if err := os.WriteFile(path, []byte(id), 0644); err != nil { blob, merr := json.MarshalIndent(clientIDFile{ID: id}, "", " ")
if merr != nil {
log.Printf("couldn't encode client-id.txt (%v): using a fresh id every startup", merr)
return id
}
if err := os.WriteFile(path, blob, 0644); err != nil {
log.Printf("couldn't save client-id.txt (%v): using a fresh id every startup", err) log.Printf("couldn't save client-id.txt (%v): using a fresh id every startup", err)
} }
return id return id
@@ -345,7 +359,7 @@ func writeSampleConfig() {
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
return return
} }
if err := os.WriteFile(path, []byte(sampleConfig), 0644); err != nil { if err := os.WriteFile(path, []byte(sampleConfig), 0600); err != nil {
log.Printf("couldn't write the sample config.toml: %v", err) log.Printf("couldn't write the sample config.toml: %v", err)
return return
} }
+14
View File
@@ -0,0 +1,14 @@
{ pkgs ? import <nixpkgs> { } }:
pkgs.mkShell {
packages = with pkgs; [
go
gopls
];
shellHook = ''
echo "DeathWatch development shell"
echo "Go: $(go version)"
echo "Run: go test ./..."
'';
}