2 Commits

Author SHA1 Message Date
b886f9d222 Add terminal package with secure ReadPassword helper
Provides echo-suppressed password prompting via golang.org/x/term for
CLI login commands. Added as a platform standard in engineering-standards.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 11:10:06 -07:00
ebe2079a83 Migrate module path from kyle/ to mc/ org
All import paths updated from git.wntrmute.dev/kyle/mcdsl to
git.wntrmute.dev/mc/mcdsl to match the Gitea organization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 02:03:45 -07:00
19 changed files with 68 additions and 27 deletions

View File

@@ -27,7 +27,7 @@ problem, usable independently or together.
### Module Path ### Module Path
``` ```
git.wntrmute.dev/kyle/mcdsl git.wntrmute.dev/mc/mcdsl
``` ```
### Dependencies ### Dependencies
@@ -39,7 +39,7 @@ git.wntrmute.dev/kyle/mcdsl
| `github.com/pelletier/go-toml/v2` | TOML config parsing | | `github.com/pelletier/go-toml/v2` | TOML config parsing |
| `google.golang.org/grpc` | gRPC server | | `google.golang.org/grpc` | gRPC server |
| `github.com/klauspost/compress/zstd` | Zstandard compression for archives | | `github.com/klauspost/compress/zstd` | Zstandard compression for archives |
| `git.wntrmute.dev/kyle/mcias/clients/go` | MCIAS client library | | `git.wntrmute.dev/mc/mcias/clients/go` | MCIAS client library |
All dependencies are already used by existing services. MCDSL adds no new All dependencies are already used by existing services. MCDSL adds no new
dependencies to the platform. dependencies to the platform.

View File

@@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
MCDSL (Metacircular Dynamics Standard Library) is the shared Go library for the Metacircular platform. It extracts common patterns from production services into reusable, tested packages. MCDSL is not a deployed service — it is imported by other services. MCDSL (Metacircular Dynamics Standard Library) is the shared Go library for the Metacircular platform. It extracts common patterns from production services into reusable, tested packages. MCDSL is not a deployed service — it is imported by other services.
**Module path:** `git.wntrmute.dev/kyle/mcdsl` **Module path:** `git.wntrmute.dev/mc/mcdsl`
## Build Commands ## Build Commands
@@ -37,6 +37,7 @@ go test ./auth/ -run TestCacheExpiry
| `web` | Session cookies, auth middleware, template rendering for htmx UIs | | `web` | Session cookies, auth middleware, template rendering for htmx UIs |
| `health` | REST and gRPC health check handlers | | `health` | REST and gRPC health check handlers |
| `archive` | tar.zst snapshots with SQLite-aware backup (VACUUM INTO) | | `archive` | tar.zst snapshots with SQLite-aware backup (VACUUM INTO) |
| `terminal` | Secure terminal input (echo-suppressed password prompts) |
## Import Pattern ## Import Pattern
@@ -44,11 +45,11 @@ Services import individual packages with aliased imports:
```go ```go
import ( import (
mcdslauth "git.wntrmute.dev/kyle/mcdsl/auth" mcdslauth "git.wntrmute.dev/mc/mcdsl/auth"
mcdsldb "git.wntrmute.dev/kyle/mcdsl/db" mcdsldb "git.wntrmute.dev/mc/mcdsl/db"
mcdslconfig "git.wntrmute.dev/kyle/mcdsl/config" mcdslconfig "git.wntrmute.dev/mc/mcdsl/config"
"git.wntrmute.dev/kyle/mcdsl/httpserver" "git.wntrmute.dev/mc/mcdsl/httpserver"
"git.wntrmute.dev/kyle/mcdsl/grpcserver" "git.wntrmute.dev/mc/mcdsl/grpcserver"
) )
``` ```
@@ -63,6 +64,7 @@ db --> (modernc.org/sqlite)
grpcserver --> auth, config grpcserver --> auth, config
health --> db health --> db
httpserver --> config httpserver --> config
terminal --> (golang.org/x/term)
web --> auth, csrf web --> auth, csrf
``` ```

View File

@@ -91,11 +91,11 @@ Remaining mcat-specific code:
- `web/` — templates and static assets (unchanged) - `web/` — templates and static assets (unchanged)
Dependencies removed: Dependencies removed:
- `git.wntrmute.dev/kyle/mcias/clients/go` (mcdsl/auth handles MCIAS directly) - `git.wntrmute.dev/mc/mcias/clients/go` (mcdsl/auth handles MCIAS directly)
- `github.com/pelletier/go-toml/v2` (now indirect via mcdsl/config) - `github.com/pelletier/go-toml/v2` (now indirect via mcdsl/config)
Dependencies added: Dependencies added:
- `git.wntrmute.dev/kyle/mcdsl` (local replace directive) - `git.wntrmute.dev/mc/mcdsl` (local replace directive)
Result: vet clean, lint 0 issues, builds successfully. Result: vet clean, lint 0 issues, builds successfully.

View File

@@ -10,7 +10,7 @@ code first).
## Phase 0: Project Setup ## Phase 0: Project Setup
- [ ] Initialize Go module (`git.wntrmute.dev/kyle/mcdsl`) - [ ] Initialize Go module (`git.wntrmute.dev/mc/mcdsl`)
- [ ] Create `.golangci.yaml` (matching platform standard) - [ ] Create `.golangci.yaml` (matching platform standard)
- [ ] Create `Makefile` with standard targets (build, test, vet, lint, all) - [ ] Create `Makefile` with standard targets (build, test, vet, lint, all)
- [ ] Create `.gitignore` - [ ] Create `.gitignore`

View File

@@ -25,7 +25,7 @@ it and provide only their service-specific logic.
## Module Path ## Module Path
``` ```
git.wntrmute.dev/kyle/mcdsl git.wntrmute.dev/mc/mcdsl
``` ```
## Packages ## Packages
@@ -46,10 +46,10 @@ git.wntrmute.dev/kyle/mcdsl
```go ```go
import ( import (
"git.wntrmute.dev/kyle/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
"git.wntrmute.dev/kyle/mcdsl/db" "git.wntrmute.dev/mc/mcdsl/db"
"git.wntrmute.dev/kyle/mcdsl/config" "git.wntrmute.dev/mc/mcdsl/config"
"git.wntrmute.dev/kyle/mcdsl/httpserver" "git.wntrmute.dev/mc/mcdsl/httpserver"
) )
// Load config with standard sections + service-specific fields. // Load config with standard sections + service-specific fields.

View File

@@ -20,7 +20,7 @@ import (
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
"git.wntrmute.dev/kyle/mcdsl/db" "git.wntrmute.dev/mc/mcdsl/db"
) )
// defaultExcludePatterns are always excluded from snapshots. // defaultExcludePatterns are always excluded from snapshots.

View File

@@ -7,7 +7,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"git.wntrmute.dev/kyle/mcdsl/db" "git.wntrmute.dev/mc/mcdsl/db"
) )
// setupServiceDir creates a realistic /srv/<service>/ directory. // setupServiceDir creates a realistic /srv/<service>/ directory.

View File

@@ -34,7 +34,7 @@ import (
"github.com/pelletier/go-toml/v2" "github.com/pelletier/go-toml/v2"
"git.wntrmute.dev/kyle/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
) )
// Base contains the configuration sections common to all Metacircular // Base contains the configuration sections common to all Metacircular

3
go.mod
View File

@@ -1,4 +1,4 @@
module git.wntrmute.dev/kyle/mcdsl module git.wntrmute.dev/mc/mcdsl
go 1.25.7 go 1.25.7
@@ -18,6 +18,7 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/net v0.48.0 // indirect golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/term v0.41.0 // indirect
golang.org/x/text v0.32.0 // indirect golang.org/x/text v0.32.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/protobuf v1.36.10 // indirect google.golang.org/protobuf v1.36.10 // indirect

2
go.sum
View File

@@ -49,6 +49,8 @@ golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=

View File

@@ -21,7 +21,7 @@ import (
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"git.wntrmute.dev/kyle/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
) )
// MethodMap classifies gRPC methods for access control. // MethodMap classifies gRPC methods for access control.

View File

@@ -13,7 +13,7 @@ import (
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"git.wntrmute.dev/kyle/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
) )
func mockMCIAS(t *testing.T) *httptest.Server { func mockMCIAS(t *testing.T) *httptest.Server {

View File

@@ -10,7 +10,7 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
"git.wntrmute.dev/kyle/mcdsl/db" "git.wntrmute.dev/mc/mcdsl/db"
) )
func TestHandlerHealthy(t *testing.T) { func TestHandlerHealthy(t *testing.T) {

View File

@@ -13,7 +13,7 @@ import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"git.wntrmute.dev/kyle/mcdsl/config" "git.wntrmute.dev/mc/mcdsl/config"
) )
// Server wraps a chi router and an http.Server with the standard // Server wraps a chi router and an http.Server with the standard

View File

@@ -9,7 +9,7 @@ import (
"testing" "testing"
"time" "time"
"git.wntrmute.dev/kyle/mcdsl/config" "git.wntrmute.dev/mc/mcdsl/config"
) )
func testConfig() config.ServerConfig { func testConfig() config.ServerConfig {

22
terminal/terminal.go Normal file
View File

@@ -0,0 +1,22 @@
// Package terminal provides secure terminal input helpers for CLI tools.
package terminal
import (
"fmt"
"os"
"golang.org/x/term"
)
// ReadPassword prints the given prompt to stderr and reads a password
// from the terminal with echo disabled. It prints a newline after the
// input is complete so the cursor advances normally.
func ReadPassword(prompt string) (string, error) {
fmt.Fprint(os.Stderr, prompt)
b, err := term.ReadPassword(int(os.Stdin.Fd())) //nolint:gosec // fd fits in int
fmt.Fprintln(os.Stderr)
if err != nil {
return "", err
}
return string(b), nil
}

14
terminal/terminal_test.go Normal file
View File

@@ -0,0 +1,14 @@
package terminal
import (
"testing"
)
func TestReadPasswordNotATTY(t *testing.T) {
// When stdin is not a terminal (e.g. in CI), ReadPassword should
// return an error rather than hanging or panicking.
_, err := ReadPassword("Password: ")
if err == nil {
t.Fatal("expected error when stdin is not a terminal")
}
}

View File

@@ -8,7 +8,7 @@ import (
"io/fs" "io/fs"
"net/http" "net/http"
"git.wntrmute.dev/kyle/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
) )
// SetSessionCookie sets a session cookie with the standard Metacircular // SetSessionCookie sets a session cookie with the standard Metacircular

View File

@@ -9,7 +9,7 @@ import (
"testing" "testing"
"testing/fstest" "testing/fstest"
"git.wntrmute.dev/kyle/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
) )
func TestSetSessionCookie(t *testing.T) { func TestSetSessionCookie(t *testing.T) {