Files
mcias/proto/mcias/v1/common.proto
Kyle Isom 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 ./...)
2026-03-11 14:38:47 -07:00

46 lines
1.4 KiB
Protocol Buffer

// Common message types shared across MCIAS gRPC services.
syntax = "proto3";
package mcias.v1;
option go_package = "git.wntrmute.dev/kyle/mcias/gen/mcias/v1;mciasv1";
import "google/protobuf/timestamp.proto";
// Account represents a user or service identity. Credential fields
// (password_hash, totp_secret) are never included in any response.
message Account {
string id = 1; // UUID
string username = 2;
string account_type = 3; // "human" or "system"
string status = 4; // "active", "inactive", or "deleted"
bool totp_enabled = 5;
google.protobuf.Timestamp created_at = 6;
google.protobuf.Timestamp updated_at = 7;
}
// TokenInfo describes an issued token by its JTI (never the raw value).
message TokenInfo {
string jti = 1;
google.protobuf.Timestamp issued_at = 2;
google.protobuf.Timestamp expires_at = 3;
google.protobuf.Timestamp revoked_at = 4; // zero if not revoked
}
// PGCreds holds Postgres connection details. Password is decrypted and
// present only when explicitly requested via GetPGCreds; it is never
// included in list responses.
message PGCreds {
string host = 1;
string database = 2;
string username = 3;
string password = 4; // security: only populated on explicit get
int32 port = 5;
}
// Error is the canonical error detail embedded in gRPC status details.
message Error {
string message = 1;
string code = 2;
}