commit de0551c627c36c8ab5f039b30ceb6616efbc5241 Author: Kyle Isom Date: Wed Mar 11 11:14:19 2026 -0700 Initial import. diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..c4259a8 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,124 @@ +# golangci-lint configuration for a security-critical IAM system. +# Principle: fail loudly. Security and correctness issues are errors, not warnings. + +run: + timeout: 5m + # Include test files so security rules apply to test helpers too. + tests: true + +linters: + disable-all: true + enable: + # --- Correctness --- + # Unhandled errors are silent failures; in auth code they become vulnerabilities. + - errcheck + # go vet: catches printf-verb mismatches, unreachable code, suspicious constructs. + - govet + # Detects assignments whose result is never used; dead writes hide logic bugs. + - ineffassign + # Reports code that is never executed. + - deadcode + # Detects variables and functions that are never used. + - unused + + # --- Error handling --- + # Enforces proper error wrapping (errors.Is/As instead of == comparisons) and + # prevents accidental discard of wrapped sentinel errors. + - errorlint + # Detects returning (nil, nil) from functions that return (value, error), which + # is almost always a logic error in auth flows. + - nilnil + + # --- Security --- + # Primary security scanner: hardcoded secrets, weak RNG, insecure crypto + # (MD5/SHA1/DES/RC4), SQL injection, insecure TLS, file permission issues, etc. + - gosec + # Deep static analysis: deprecated APIs, incorrect mutex use, unreachable code, + # incorrect string conversions, and hundreds of other checks. + - staticcheck + # Detects integer overflow-prone conversions (e.g., int64 → int32) that can + # corrupt length or index calculations in crypto/auth code. + - gosimple + + # --- Style / conventions (per CLAUDE.md) --- + # Enforces gofmt formatting. Non-formatted code is a CI failure. + - gofmt + # Manages import grouping and formatting; catches stray debug imports. + - goimports + # Enforces Go naming conventions and exported-symbol documentation. + - revive + +linters-settings: + errcheck: + # Treat blank-identifier assignment of errors as a failure: `_ = riskyCall()` + check-blank: true + # Also check error returns from type assertions. + check-type-assertions: true + + govet: + # Enable all analyzers, including shadow (variable shadowing is dangerous in + # auth code where an outer `err` may be silently clobbered). + enable-all: true + + gosec: + # Treat all gosec findings as errors, not warnings. + severity: medium + confidence: medium + excludes: + # G104 (errors unhandled) overlaps with errcheck; let errcheck own this. + - G104 + + errorlint: + errorf: true + asserts: true + comparison: true + + gofmt: + simplify: true + + revive: + rules: + - name: exported + severity: warning + - name: error-return + severity: error + - name: error-strings + severity: warning + - name: if-return + severity: warning + - name: increment-decrement + severity: warning + - name: var-naming + severity: warning + - name: package-comments + severity: warning + - name: range + severity: warning + - name: time-naming + severity: warning + - name: unexported-return + severity: error + - name: indent-error-flow + severity: warning + - name: early-return + severity: warning + +issues: + # Do not cap the number of reported issues; in security code every finding matters. + max-issues-per-linter: 0 + max-same-issues: 0 + + # Exclude vendor and generated code only. + exclude-dirs: + - vendor + exclude-files: + - ".*\\.pb\\.go$" + - ".*_gen\\.go$" + + exclude-rules: + # In test files, allow hardcoded test credentials (gosec G101) since they are + # intentional fixtures, not production secrets. + - path: "_test\\.go" + linters: + - gosec + text: "G101" diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6e5248f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,74 @@ +# CLAUDE.md + +## Project Overview + +MCIAS (Metacircular Identity and Access System) is a single-sign-on (SSO) and Identity & Access Management (IAM) system for personal projects. The target audience is a single developer building personal apps, with support for onboarding friends onto those apps. + +**Priorities (in order):** security, robustness, correctness. Performance is secondary. + +## Tech Stack + +- **Language:** Go +- **Database:** SQLite +- **Logging/Utilities:** git.wntrmute.dev/kyle/goutils +- **Crypto:** Ed25519 (signatures), Argon2 (password hashing) +- **Tokens:** JWT signed with Ed25519 (algorithm: EdDSA); always validate the `alg` header on receipt — never accept `none` or symmetric algorithms +- **Auth:** Username/password + optional TOTP; future FIDO/Yubikey support + +## Binaries + +- `mciassrv` — authentication server (REST API over HTTPS/TLS) +- `mciasctl` — admin CLI for account/token/credential management + +## Development Workflow + +If PROGRESS.md does not yet exist, create it before proceeding. It is the source of truth for current state. + +1. Check PROGRESS.md for current state and next steps +2. Define discrete next steps with actionable acceptance criteria +3. Implement, adversarially verify correctness, write tests +4. Commit to git, update PROGRESS.md +5. Repeat + +## Security Constraints + +This is a security-critical project. The following rules are non-negotiable: + +- Never implement custom crypto. Use standard library (`crypto/...`) or well-audited packages only. +- Always validate the `alg` header in JWTs before processing; reject `none` and any non-EdDSA algorithm. +- Argon2id parameters must meet current OWASP recommendations; never reduce them for convenience. +- Credential storage (passwords, tokens, secrets) must never appear in logs, error messages, or API responses. +- Any code touching authentication flows, token issuance/validation, or credential storage must include a comment citing the rationale for each security decision. +- When in doubt about a crypto or auth decision, halt and ask rather than guess. +- Review all crypto primitives against current best practices before use; flag any deviation in the commit body. + +## Testing Requirements + +- Tests live alongside source in the same package, using the `_test.go` suffix +- Run with `go test ./...`; CI must pass with zero failures +- Unit tests for all exported functions and security-critical internal functions +- Integration tests for all subsystems (database layer, token issuance, auth flows) +- End-to-end tests for complete login, token renewal, and revocation flows +- Adversarially verify all outputs: test invalid inputs, boundary conditions, and known attack patterns (e.g., JWT `alg` confusion, timing attacks on credential comparison) +- Use `crypto/subtle.ConstantTimeCompare` wherever token or credential equality is checked + +## Git Commit Style + +- First line: single line, max 55 characters +- Body (optional): bullet points describing work done +- Security-sensitive changes (crypto primitives, auth flows, token handling, credential storage, session management) must be explicitly flagged in the commit body with a `Security:` line describing what changed and why it is safe + +## Go Conventions + +- Format all code with `gofmt` before committing +- Lint with `golangci-lint`; resolve all warnings unless explicitly justified +- Wrap errors with `fmt.Errorf("context: %w", err)` to preserve stack context +- Prefer explicit error handling over panics; never silently discard errors +- Use `log/slog` (or goutils equivalents) for structured logging; never `fmt.Println` in production paths + +## Key Documents + +- `PROJECT.md` — Project specifications and requirements +- `ARCHITECTURE.md` — **Required before any implementation.** Covers token lifecycle, session management, multi-app trust boundaries, and database schema. Do not generate code until this document exists. +- `PROJECT_PLAN.md` — Discrete implementation steps (to be written) +- `PROGRESS.md` — Development progress tracking (to be written) diff --git a/PROJECT.md b/PROJECT.md new file mode 100644 index 0000000..305cd24 --- /dev/null +++ b/PROJECT.md @@ -0,0 +1,69 @@ +# MCIAS + +We are building a single-signon and IAM system for personal projects. + +## Background + +The Metacircular Identity and Access System (MCIAS) provides standard +tools for user and access management among metacircular and wntrmute +systems. + +In particular, the target audience is a single developer building +personal apps. It should be easy to use MCIAS to facilitate onboarding +friends onto these personal apps. + +MCIAS is a foundational security and identity system. As such, the +highest priorities are for security, robustness, and correctness. +Performance is secondary, and can be tuned later. + +## Specifications + ++ Applications should be able to either do an interactive login, using a + username/password (and potentially a TOTP), or present a token. ++ Applications should be able to renew the token, which would nominally + expire after some period (defaulting to maybe 30 days). ++ There are two kinds of users: human and system accounts. ++ System accounts can only present a token; they have a single token + associated with that account at a time. ++ User accounts have roles associated with them. ++ Users with the admin role can issue tokens for any app, or users with + the role named the same as a service account can issue tokens for that + service account. ++ Admin users can also revoke tokens for a service account. ++ Service accounts (and users with the a role named the same as the + service account) can also retrieve Postgres database credentials for + the service account. ++ Human accounts should eventually support FIDO logins and Yubikey auth, + but the first pass only needs username, password, and optional TOTP. + +## Technical details + ++ User passwords will be stored using scrypt. ++ The service account tokens and user/password authentication can be + used to obtain a JWT, if that is appropriate. ++ All authentication events should be logged. ++ This service should use the packages contained in + git.wntrmute.dev/kyle/goutils for logging etc. ++ The database should be sqlite. ++ Modern cryptography should be used. Preference should be given to + Ed25519 as the public algorithm for signatures, for example. Consider + the use of Argon2 for password hashes. + +## Interfaces + ++ The primary interface will be an REST API over HTTPS. TLS security is + critical for this. + + We will also need to build client libraries in several languages + later on. ++ There should be two command line tools associated with MCIAS: + + mciassrv is the authentication server. + + mciasctl is the tool for admins to create and manage accounts, issue + or revoke tokens, and manage postgres database credentials. + +## Notes + ++ We need an explicit security model. ++ This is a system for small, personal services. Manual user lifecycle + managment is acceptable and expected. Federation is an explicit + nongoal. ++ Strong testing is a requirement. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8dcd225 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +The project notes are in PROJECT.md. + +Before starting the project, read the project description and develop a +system architecture document (ARCHITECTURE.md). It should describe the +technical design of the system. Then, PROJECT_PLAN.md should be written +that describes how to build this system in discrete steps. + +Commit these files to Git after human review. For this project, all git +commits should have a single first line, no more than 55 characters, +that succinctly describes an overview of the changes. As necessary, the +body of the commit message should contain bullets describing the work +that was done. + +Then, create PROGRESS.md. This should be initialized with the first +steps for the project. + +The development process for this should generally be: + +1. Determine the current state of the project. Track the progress in + PROGRESS.md, explicitly stating what was done and next steps. +2. Develop reasonable, discrete next steps to move forward with + actionable acceptance criteria. +3. Complete the next steps. + + You should adversarially check whether any outputs are correct. + + All code units should be thoroughly unit tested. + + All subsystems should be thoroughly integration tested. + + Where appropriate, end-to-end tests to validate the system should + be developed. +4. Checkpoint your work, committing it to git. + +Repeat this cycle until the system is in the desired end state.