Commit Graph

  • 39d9ffb79a Add service-context login policy enforcement master Kyle Isom 2026-03-16 21:09:38 -07:00
  • b0afe3b993 Align with engineering standards (steps 1-5) Kyle Isom 2026-03-16 20:26:43 -07:00
  • 446b3df52d Fix WebAuthn CSRF; clarify security key UI Kyle Isom 2026-03-16 19:27:44 -07:00
  • 0b37fde155 Add WebAuthn config; Docker single-mount Kyle Isom 2026-03-16 18:57:06 -07:00
  • 37afc68287 Add TOTP enrollment to web UI v1.7.0 Kyle Isom 2026-03-16 17:39:45 -07:00
  • 25417b24f4 Add FIDO2/WebAuthn passkey authentication Kyle Isom 2026-03-16 16:12:59 -07:00
  • 19fa0c9a8e Fix policy form roles; add JSON edit mode Claude Opus 4.6 2026-03-16 15:21:26 -07:00
  • 7db560dae4 Update PROGRESS.md for docker-clean target Kyle Isom 2026-03-15 20:38:58 -07:00
  • 124d0cdcd1 Add docker image cleanup to clean target Kyle Isom 2026-03-15 20:38:38 -07:00
  • cf1f4f94be Fix Swagger server URLs to use correct hosts Kyle Isom 2026-03-15 20:33:39 -07:00
  • 52cc979814 Update PROGRESS.md: /docs swagger fix Kyle Isom 2026-03-15 19:19:29 -07:00
  • 8bf5c9033f Bundle swagger-ui assets locally for /docs Kyle Isom 2026-03-15 19:19:12 -07:00
  • cb661bb8f5 Checkpoint: fix all lint warnings Kyle Isom 2026-03-15 16:40:11 -07:00
  • 9657f18784 Fix OpenAPI spec parsing errors in Swagger UI v1.6.0 Kyle Isom 2026-03-15 16:29:53 -07:00
  • d4e8ef90ee Add policy-based authz and token delegation Kyle Isom 2026-03-15 14:40:16 -07:00
  • d6cc82755d Add username to token validate response Kyle Isom 2026-03-15 14:06:11 -07:00
  • 0d38bbae00 Add mciasdb rekey command Kyle Isom 2026-03-15 13:27:29 -07:00
  • 23a27be57e Fix login card nesting on htmx failure Kyle Isom 2026-03-15 08:31:40 -07:00
  • b1b52000c4 Sync docs and fix flaky renewal e2e test v1.5.1 Kyle Isom 2026-03-15 00:39:41 -07:00
  • d87b4b4042 Add vault seal/unseal lifecycle Kyle Isom 2026-03-14 23:55:37 -07:00
  • 5c242f8abb Remediate PEN-01 through PEN-07 (pentest round 4) Kyle Isom 2026-03-14 23:14:47 -07:00
  • 1121b7d4fd Harden deployment and fix PEN-01 Kyle Isom 2026-03-14 22:33:24 -07:00
  • 2a85d4bf2b Update AUDIT.md: all SEC findings remediated v1.5.0 Kyle Isom 2026-03-14 21:31:30 -07:00
  • 8f09e0e81a Rename Go client package from mciasgoclient to mcias - Update package declaration in client.go - Update error message strings to reference new package name - Update test package and imports to use new name - Update README.md documentation and examples with new package name - All tests pass Kyle Isom 2026-03-14 19:01:07 -07:00
  • 7e5fc9f111 Fix flaky gRPC renewal test timing Kyle Isom 2026-03-13 01:08:44 -07:00
  • cf02b8e2d8 Merge SEC-01: require password for TOTP enrollment Kyle Isom 2026-03-13 01:07:39 -07:00
  • fe780bf873 Merge SEC-03: require token proximity for renewal Kyle Isom 2026-03-13 01:07:34 -07:00
  • cb96650e59 Merge SEC-11: use json.Marshal for audit details Kyle Isom 2026-03-13 01:06:55 -07:00
  • bef5a3269d Merge SEC-09: hide admin nav links from non-admin users Kyle Isom 2026-03-13 01:06:50 -07:00
  • 6191c5e00a Merge SEC-02: normalize lockout response Kyle Isom 2026-03-13 01:05:56 -07:00
  • fa45836612 Merge SEC-08: atomic system token issuance Kyle Isom 2026-03-13 00:50:39 -07:00
  • 0bc7943d8f Merge SEC-06: gRPC proxy-aware rate limiting Kyle Isom 2026-03-13 00:50:32 -07:00
  • 97ba7ab74c Merge SEC-04: API security headers Kyle Isom 2026-03-13 00:50:27 -07:00
  • 582645f9d6 Merge SEC-05: body size limit and max password length Kyle Isom 2026-03-13 00:49:39 -07:00
  • 8840317cce Merge SEC-10: add Permissions-Policy header Kyle Isom 2026-03-13 00:49:34 -07:00
  • 482300b8b1 Merge SEC-12: reduce default token expiry to 7 days Kyle Isom 2026-03-13 00:49:29 -07:00
  • 8545473703 Fix SEC-01: require password for TOTP enroll Kyle Isom 2026-03-13 00:48:31 -07:00
  • 3b17f7f70b Fix SEC-11: use json.Marshal for audit details Kyle Isom 2026-03-13 00:46:00 -07:00
  • eef7d1bc1a Fix SEC-03: require token proximity for renewal Kyle Isom 2026-03-13 00:45:35 -07:00
  • d7d7ba21d9 Fix SEC-09: hide admin nav links from non-admin users Kyle Isom 2026-03-13 00:44:30 -07:00
  • 4d3d438253 Fix SEC-02: normalize lockout response Kyle Isom 2026-03-13 00:43:57 -07:00
  • 7cc2c86300 Fix SEC-12: reduce default token expiry to 7 days Kyle Isom 2026-03-13 00:43:20 -07:00
  • 51a5277062 Fix SEC-08: make system token issuance atomic Kyle Isom 2026-03-13 00:43:13 -07:00
  • d3b63b1f87 Fix SEC-06: proxy-aware gRPC rate limiting Kyle Isom 2026-03-13 00:43:09 -07:00
  • 70e4f715f7 Fix SEC-05: add body size limit to REST API and max password length Kyle Isom 2026-03-13 00:42:11 -07:00
  • 3f09d5eb4f Fix SEC-04: add security headers to API Kyle Isom 2026-03-13 00:41:48 -07:00
  • 036a0b8be4 Fix SEC-07: disable static file directory listing Kyle Isom 2026-03-13 00:41:46 -07:00
  • 30fc3470fa Fix SEC-10: add Permissions-Policy header Kyle Isom 2026-03-13 00:41:20 -07:00
  • 586d4e3355 Allow non-admin users to access dashboard Kyle Isom 2026-03-12 23:40:21 -07:00
  • 394a9fb754 Update docs for recent changes Kyle Isom 2026-03-12 23:07:41 -07:00
  • 1c16354725 fix UI privilege escalation vulnerability v1.4.0 Kyle Isom 2026-03-12 21:59:02 -07:00
  • 89f78a38dd Update web UI to support all compile-time roles - Update knownRoles to include guest, viewer, editor, and commenter - Replace hardcoded role strings with model constants - Remove obsolete 'service' role from UI - All tests pass Kyle Isom 2026-03-12 21:14:22 -07:00
  • 4d6c5cb67c Add guest, viewer, editor, and commenter roles to compile-time allowlist - Add RoleGuest, RoleViewer, RoleEditor, and RoleCommenter constants - Update allowedRoles map to include new roles - Update ValidateRole error message with complete role list - All tests pass; build verified v1.3.0 Kyle Isom 2026-03-12 21:03:24 -07:00
  • f880bbb6de Add granular role grant/revoke endpoints to REST and gRPC APIs - Add POST /v1/accounts/{id}/roles and DELETE /v1/accounts/{id}/roles/{role} REST endpoints - Add GrantRole and RevokeRole RPCs to AccountService in gRPC API - Update OpenAPI specification with new endpoints - Add grant and revoke subcommands to mciasctl - Add grant and revoke subcommands to mciasgrpcctl - Regenerate proto files with new message types and RPCs - Implement gRPC server methods for granular role management - All existing tests pass; build verified with goimports Security: Role changes are audited via EventRoleGranted and EventRoleRevoked events, consistent with existing SetRoles implementation. Kyle Isom 2026-03-12 20:55:49 -07:00
  • d3d656a23f grpcctl: add auth login and policy commands Kyle Isom 2026-03-12 20:51:10 -07:00
  • 28bc33a96d clients: expand Go, Python, Rust client APIs v1.2.0 Kyle Isom 2026-03-12 20:29:11 -07:00
  • 98ed858c67 trusted proxy, TOTP replay protection, new tests Kyle Isom 2026-03-12 17:44:01 -07:00
  • 35f27b7c4f UI: password change enforcement + migration recovery Kyle Isom 2026-03-12 15:33:19 -07:00
  • 25d550a066 ignore env file v1.1.0 Kyle Isom 2026-03-12 14:39:14 -07:00
  • 5d7d2cfc08 Checkpoint: password reset, rule expiry, migrations Kyle Isom 2026-03-12 14:38:38 -07:00
  • 833775de83 db: integrate golang-migrate for schema migrations - internal/db/migrations/: five embedded SQL files containing the migration SQL previously held as Go string literals. Files follow the NNN_description.up.sql naming convention required by golang-migrate's iofs source. - internal/db/migrate.go: rewritten to use github.com/golang-migrate/migrate/v4 with the database/sqlite driver (modernc.org/sqlite, pure Go) and source/iofs for compile-time embedded SQL. - newMigrate() opens a dedicated *sql.DB so m.Close() does not affect the caller's shared connection. - Migrate() includes a compatibility shim: reads the legacy schema_version table and calls m.Force(v) before m.Up() so existing databases are not re-migrated. - LatestSchemaVersion promoted from var to const. - internal/db/db.go: added path field to DB struct; Open() translates ':memory:' to a named shared-cache URI (file:mcias_N?mode=memory&cache=shared) so the migration runner can open a second connection to the same in-memory database without sharing the handle that golang-migrate will close on teardown. - go.mod: added golang-migrate/migrate/v4 v4.19.1 (direct). All callers unchanged. All tests pass; golangci-lint clean. Kyle Isom 2026-03-12 11:52:39 -07:00
  • 562aad908e UI: pgcreds create button; show logged-in user Kyle Isom 2026-03-12 11:38:57 -07:00
  • 68df2eee23 Release v1.0.0 v1.0.0 Kyle Isom 2026-03-11 23:29:29 -07:00
  • 3d0eff9e0e docker: also tag image as mcias:latest Kyle Isom 2026-03-11 23:29:11 -07:00
  • 614c83c803 Add PG creds + policy/tags UI; fix lint and build Kyle Isom 2026-03-11 23:24:03 -07:00
  • fdcc117c89 Fix UI: install real HTMX, add PG creds and roles UI - web/static/htmx.min.js: replace placeholder stub with htmx 2.0.4 (downloaded from unpkg.com). The placeholder only logged a console warning; no HTMX features worked, so form submissions fell back to native POSTs and the account_row fragment was returned as a raw HTML body rather than spliced into the table. This was the root cause of account creation appearing to 'do nothing'. - internal/ui/ui.go: add pgcreds_form.html to shared template list; add PUT /accounts/{id}/pgcreds route; reorder AccountDetailData fields so embedded PageData does not shadow Account. - internal/ui/handlers_accounts.go: add handleSetPGCreds handler — encrypts the submitted password with AES-256-GCM using the server master key before storage, validates system-account-only constraint, re-reads and re-renders the fragment after save. Add PGCred field population to handleAccountDetail. - internal/ui/ui_test.go: add tests for account creation, role management, and PG credential handlers. - web/templates/account_detail.html: add Postgres Credentials card for system accounts. - web/templates/fragments/pgcreds_form.html: new fragment for the PG credentials form; CSRF token is supplied via the body-level hx-headers attribute in base.html. Security: PG password is encrypted with AES-256-GCM (crypto.SealAESGCM) before storage; a fresh nonce is generated per call; the plaintext is never logged or returned in responses. Kyle Isom 2026-03-11 22:30:13 -07:00
  • b495a90a9d Fix F-08, F-13: Adjust lockout expiration logic and enforce password length in tests Kyle Isom 2026-03-11 21:36:04 -07:00
  • 52f5d891eb Add checkpoint instructions. Kyle Isom 2026-03-11 21:31:45 -07:00
  • 3c94c948e2 Fix F-08, F-12, F-13: Implement account lockout, username validation, and password minimum length enforcement Kyle Isom 2026-03-11 20:59:26 -07:00
  • 2dbc553abe Fix F-07: pre-compute real Argon2 dummy hash via sync.Once - auth/auth.go: add DummyHash() which uses sync.Once to compute HashPassword("dummy-password-for-timing-only", DefaultArgonParams()) on first call; subsequent calls return the cached PHC string; add sync to imports - auth/auth_test.go: TestDummyHashIsValidPHC verifies the hash parses and verifies correctly; TestDummyHashIsCached verifies sync.Once behaviour; TestDummyHashMatchesDefaultParams verifies embedded m/t/p match DefaultArgonParams() - server/server.go, grpcserver/auth.go, ui/ui.go: replace five hardcoded PHC strings with auth.DummyHash() calls - AUDIT.md: mark F-07 as fixed Security: the previous hardcoded hash used a 6-byte salt and 6-byte output ("testsalt"/"testhash" in base64), which Argon2id verifies faster than a real 16-byte-salt / 32-byte-output hash. This timing gap was measurable and could aid user enumeration. auth.DummyHash() uses identical parameters and full-length salt and output, so dummy verification timing matches real timing exactly, regardless of future parameter changes. Kyle Isom 2026-03-11 20:37:27 -07:00
  • 06ec8be1c9 Fix F-16: revoke old system token before issuing new one - ui/handlers_accounts.go (handleIssueSystemToken): call GetSystemToken before issuing; if one exists, call RevokeToken(existing.JTI, "rotated") before TrackToken and SetSystemToken for the new token; mirrors the pattern in REST handleTokenIssue and gRPC IssueServiceToken - db/db_test.go: TestSystemTokenRotationRevokesOld verifies the full rotation flow: old JTI revoked with reason "rotated", new JTI tracked and active, GetSystemToken returns the new JTI - AUDIT.md: mark F-16 as fixed Security: without this fix an old system token remained valid after rotation until its natural expiry, giving a leaked or stolen old token extra lifetime. With the revocation the old JTI is immediately marked in token_revocation so any validator checking revocation status rejects it. Kyle Isom 2026-03-11 20:34:57 -07:00
  • e20b66d6f6 Fix F-02: replace password-in-hidden-field with nonce - ui/ui.go: add pendingLogin struct and pendingLogins sync.Map to UIServer; add issueTOTPNonce (generates 128-bit random nonce, stores accountID with 90s TTL) and consumeTOTPNonce (single-use, expiry-checked LoadAndDelete); add dummyHash() method - ui/handlers_auth.go: split handleLoginPost into step 1 (password verify → issue nonce) and step 2 (handleTOTPStep, consume nonce → validate TOTP) via a new finishLogin helper; password never transmitted or stored after step 1 - ui/ui_test.go: refactor newTestMux to reuse new newTestUIServer; add TestTOTPNonceIssuedAndConsumed, TestTOTPNonceUnknownRejected, TestTOTPNonceExpired, and TestLoginPostPasswordNotInTOTPForm; 11/11 tests pass - web/templates/fragments/totp_step.html: replace 'name=password' hidden field with 'name=totp_nonce' - db/accounts.go: add GetAccountByID for TOTP step lookup - AUDIT.md: mark F-02 as fixed Security: the plaintext password previously survived two HTTP round-trips and lived in the browser DOM during the TOTP step. The nonce approach means the password is verified once and immediately discarded; only an opaque random token tied to an account ID (never a credential) crosses the wire on step 2. Nonces are single-use and expire after 90 seconds to limit the window if one is captured. Kyle Isom 2026-03-11 20:33:04 -07:00
  • 0e201ae05b Fix F-03: make token renewal atomic - db/accounts.go: add RenewToken(oldJTI, reason, newJTI, accountID, issuedAt, expiresAt) which wraps RevokeToken + TrackToken in a single BEGIN/COMMIT transaction; if either step fails the whole tx rolls back, so the user is never left with neither old nor new token valid - server.go (handleRenewToken): replace separate RevokeToken + TrackToken calls with single RenewToken call; failure now returns 500 instead of silently losing revocation - grpcserver/auth.go (RenewToken): same replacement - db/db_test.go: TestRenewTokenAtomic verifies old token is revoked with correct reason, new token is tracked and not revoked, and a second renewal on the already-revoked old token returns an error - AUDIT.md: mark F-03 as fixed Security: without atomicity a crash/error between revoke and track could leave the old token active alongside the new one (two live tokens) or revoke the old token without tracking the new one (user locked out). The transaction ensures exactly one of the two tokens is valid at all times. Kyle Isom 2026-03-11 20:24:32 -07:00
  • c8f1ac6dac Fix F-01: TOTP enroll must not set required=1 early - db/accounts.go: add StorePendingTOTP() which writes totp_secret_enc and totp_secret_nonce but leaves totp_required=0; add comment explaining two-phase flow - server.go (handleTOTPEnroll): switch from SetTOTP() to StorePendingTOTP() so the required flag is only set after the user confirms a valid TOTP code via handleTOTPConfirm, which still calls SetTOTP() - server_test.go: TestTOTPEnrollDoesNotRequireTOTP verifies that after POST /v1/auth/totp/enroll, TOTPRequired is false and the encrypted secret is present; confirms that a subsequent login without a TOTP code still succeeds (no lockout) - AUDIT.md: mark F-01 and F-11 as fixed Security: without this fix an admin who enrolls TOTP but abandons before confirmation is permanently locked out because totp_required=1 but no confirmed secret exists. StorePendingTOTP() keeps the secret pending until the user proves possession by confirming a valid code. Kyle Isom 2026-03-11 20:18:57 -07:00
  • 47847a4312 Fix F-04 + F-11; add AUDIT.md - AUDIT.md: security audit report with 16 findings (F-01..F-16) - F-04 (server.go): wire loginRateLimit (10 req/s, burst 10) to POST /v1/auth/login and POST /v1/token/validate; no limit on /v1/health or public-key endpoints - F-04 (server_test.go): TestLoginRateLimited uses concurrent goroutines (sync.WaitGroup) to fire burst+1 requests before Argon2id completes, sidestepping token-bucket refill timing; TestTokenValidateRateLimited; TestHealthNotRateLimited - F-11 (ui.go): refactor Register() so all UI routes are mounted on a child mux wrapped with securityHeaders middleware; five headers set on every response: Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, HSTS, Referrer-Policy - F-11 (ui_test.go): 7 new tests covering login page, dashboard redirect, root redirect, static assets, CSP directives, HSTS min-age, and middleware unit behaviour Security: rate limiter on login prevents brute-force credential stuffing; security headers mitigate clickjacking (X-Frame-Options DENY), MIME sniffing (nosniff), and protocol downgrade (HSTS) Kyle Isom 2026-03-11 20:18:09 -07:00
  • f2903ca103 Fix grpcserver rate limiter: move to Server field Kyle Isom 2026-03-11 19:20:32 -07:00
  • 4d140886ca Add HTMX-based UI templates and handlers for account and audit management Kyle Isom 2026-03-11 18:02:53 -07:00
  • da4126c1a9 Implement Phase 9: client libraries (Go, Rust, Lisp, Python) - clients/README.md: canonical API surface and error type reference - clients/testdata/: shared JSON response fixtures - clients/go/: mciasgoclient package; net/http + TLS 1.2+; sync.RWMutex token state; DisallowUnknownFields on all decoders; 25 tests pass - clients/rust/: async mcias-client crate; reqwest+rustls (no OpenSSL); thiserror MciasError enum; Arc<RwLock> token state; 22+1 tests pass; cargo clippy -D warnings clean - clients/lisp/: ASDF mcias-client; dexador HTTP, yason JSON; mcias-error condition hierarchy; Hunchentoot mock-dispatcher; 37 fiveam checks pass on SBCL 2.6.1; yason boolean normalisation in validate-token - clients/python/: mcias_client package (Python 3.11+); httpx sync; py.typed; dataclasses; 32 pytest tests; mypy --strict + ruff clean - test/mock/mockserver.go: in-memory mock server for Go client tests - ARCHITECTURE.md §19: updated per-language notes to match implementation - PROGRESS.md: Phase 9 marked complete - .gitignore: exclude clients/rust/target/, python .venv, .pytest_cache, .fasl files Security: token never logged or exposed in error messages in any library; TLS enforced in all four languages; token stored under lock/mutex/RwLock Kyle Isom 2026-03-11 16:38:32 -07:00
  • f34e9a69a0 Fix all golangci-lint warnings - errorlint: use errors.Is for db.ErrNotFound comparisons in accountservice.go, credentialservice.go, tokenservice.go - gofmt/goimports: move mciasv1 alias into internal import group in auth.go, credentialservice.go, grpcserver.go, grpcserver_test.go - gosec G115: add nolint annotation on int32 port conversions in mciasgrpcctl/main.go and credentialservice.go (port validated as [1,65535] on input; overflow not reachable) - govet fieldalignment: reorder Server, grpcRateLimiter, grpcRateLimitEntry, testEnv structs to reduce GC bitmap size (96 -> 80 pointer bytes each) - ineffassign: remove intermediate grpcSrv = GRPCServer() call in cmd/mciassrv/main.go (immediately overwritten by TLS build) - staticcheck SA9003: replace empty if-body with _ = Serve(lis) in grpcserver_test.go 0 golangci-lint issues; 137 tests pass (go test -race ./...) Kyle Isom 2026-03-11 15:24:07 -07:00
  • 941c71f2d1 Implement Phase 8: operational artifacts - Makefile: build/test/lint/generate/man/install/clean/dist/docker; CGO_ENABLED=1 throughout; VERSION from git describe --tags --always - Dockerfile: multi-stage (golang:1.26-bookworm builder -> debian:bookworm-slim runtime); non-root uid 10001 (mcias), VOLUME /data, EXPOSE 8443/9443; no toolchain in final image - dist/mcias.service: hardened systemd unit (ProtectSystem=strict, ProtectHome, PrivateTmp, NoNewPrivileges, MemoryDenyWriteExecute, CapabilityBoundingSet= empty, EnvironmentFile, LimitNOFILE=65536) - dist/mcias.env.example: passphrase env file template - dist/mcias.conf.example: fully-commented production TOML config - dist/mcias-dev.conf.example: local dev config (/tmp, short expiry) - dist/mcias.conf.docker.example: container config template - dist/install.sh: POSIX sh idempotent installer; creates mcias user/group, installs binaries, /etc/mcias, /var/lib/mcias, systemd unit, man pages; prints post-install instructions - man/man1/mciassrv.1: mdoc synopsis/config/API/signals/files - man/man1/mciasctl.1: mdoc all subcommands/env/examples - man/man1/mciasdb.1: mdoc trust model/safety/all subcommands - man/man1/mciasgrpcctl.1: mdoc gRPC commands/grpcurl example - README.md: user-facing quick-start, first-run setup, build instructions, CLI references, Docker deployment, security notes - .gitignore: added /bin/, dist/mcias_*.tar.gz, man/man1/*.gz Kyle Isom 2026-03-11 15:11:36 -07:00
  • 8f706f10ec Phase 8 plan: add Dockerfile step (Step 8.6) - PROJECT_PLAN.md: insert Step 8.6 (Dockerfile) before the documentation step (renumbered to 8.7); acceptance criteria cover multi-stage build, non-root runtime user, EXPOSE ports, VOLUME /data, dist/mcias.conf.docker.example, Makefile docker target, and image size target (<50 MB) - ARCHITECTURE.md §18: add Dockerfile to artifact inventory table; add Dockerfile Design section covering build stages, security properties (no shell, non-root uid 10001, TLS inside container), operator workflow, and the new Makefile docker target Kyle Isom 2026-03-11 14:47:07 -07:00
  • 7c79d00514 Sync docs: ARCHITECTURE, PROJECT, PROJECT_PLAN - ARCHITECTURE.md §12: add mciasdb, mciasgrpcctl, internal/grpcserver, proto/, and gen/ to the directory structure diagram - ARCHITECTURE.md §17: replace buf generate references with protoc; the implementation uses protoc + protoc-gen-go + protoc-gen-go-grpc invoked via go generate ./... (proto/generate.go) - PROJECT_PLAN.md §7.1: replace buf.yaml/buf.gen.yaml acceptance criteria with the protoc-based go:generate approach actually used - PROJECT_PLAN.md §7.6: clarify that gen/ is committed to the repo (not gitignored); only the binary /mciasgrpcctl is excluded - PROJECT.md: replace scrypt with Argon2id (the actual algorithm); remove the redundant Argon2 suggestion line Kyle Isom 2026-03-11 14:44:08 -07:00
  • 59d51a1d38 Implement Phase 7: gRPC dual-stack interface - proto/mcias/v1/: AdminService, AuthService, TokenService, AccountService, CredentialService; generated Go stubs in gen/ - internal/grpcserver: full handler implementations sharing all business logic (auth, token, db, crypto) with REST server; interceptor chain: logging -> auth (JWT alg-first + revocation) -> rate-limit (token bucket, 10 req/s, burst 10, per-IP) - internal/config: optional grpc_addr field in [server] section - cmd/mciassrv: dual-stack startup; gRPC/TLS listener on grpc_addr when configured; graceful shutdown of both servers in 15s window - cmd/mciasgrpcctl: companion gRPC CLI mirroring mciasctl commands (health, pubkey, account, role, token, pgcreds) using TLS with optional custom CA cert - internal/grpcserver/grpcserver_test.go: 20 tests via bufconn covering public RPCs, auth interceptor (no token, invalid, revoked -> 401), non-admin -> 403, Login/Logout/RenewToken/ValidateToken flows, AccountService CRUD, SetPGCreds/GetPGCreds AES-GCM round-trip, credential fields absent from all responses Security: JWT validation path identical to REST: alg header checked before signature, alg:none rejected, revocation table checked after sig. Authorization metadata value never logged by any interceptor. Credential fields (PasswordHash, TOTPSecret*, PGPassword) absent from all proto response messages — enforced by proto design and confirmed by test TestCredentialFieldsAbsentFromAccountResponse. Login dummy-Argon2 timing guard preserves timing uniformity for unknown users (same as REST handleLogin). TLS required at listener level; cmd/mciassrv uses credentials.NewServerTLSFromFile; no h2c offered. 137 tests pass, zero race conditions (go test -race ./...) Kyle Isom 2026-03-11 14:38:47 -07:00
  • 094741b56d Planning updates. Kyle Isom 2026-03-11 14:15:27 -07:00
  • e63d9863b6 Implement dashboard and audit log templates, add paginated audit log support Kyle Isom 2026-03-11 14:05:08 -07:00
  • 14083b82b4 Fix linting: golangci-lint v2 config, nolint annotations Kyle Isom 2026-03-11 12:53:25 -07:00
  • 9ef913c59b Updating ARCHITECTURE.md. Kyle Isom 2026-03-11 12:19:17 -07:00
  • f02eff21b4 Complete implementation: e2e tests, gofmt, hardening - Add test/e2e: 11 end-to-end tests covering full login/logout, token renewal, admin account management, credential-never-in-response, unauthorised access, JWT alg confusion and alg:none attacks, revoked token rejection, system account token issuance, wrong-password vs unknown-user indistinguishability - Apply gofmt to all source files (formatting only, no logic changes) - Update .golangci.yaml for golangci-lint v2 (version field required, gosimple merged into staticcheck, formatters section separated) - Update PROGRESS.md to reflect Phase 5 completion Security: All 97 tests pass with go test -race ./... (zero race conditions). Adversarial JWT tests (alg confusion, alg:none) confirm the ValidateToken alg-first check is effective against both attack classes. Credential fields (PasswordHash, TOTPSecret*, PGPassword) confirmed absent from all API responses via both unit and e2e tests. go vet ./... clean. golangci-lint v2.6.2 incompatible with go1.26 runtime; go vet used as linter until toolchain is updated. Kyle Isom 2026-03-11 11:54:14 -07:00
  • d75a1d6fd3 checkpoint mciassrv Kyle Isom 2026-03-11 11:48:24 -07:00
  • 9e4e7aba7a Adding docs. Kyle Isom 2026-03-11 11:26:47 -07:00
  • de0551c627 Initial import. Kyle Isom 2026-03-11 11:14:19 -07:00