Initial import.

This commit is contained in:
2026-03-11 11:14:19 -07:00
commit de0551c627
4 changed files with 298 additions and 0 deletions

124
.golangci.yaml Normal file
View File

@@ -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"

74
CLAUDE.md Normal file
View File

@@ -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)

69
PROJECT.md Normal file
View File

@@ -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.

31
README.md Normal file
View File

@@ -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.