diff --git a/ci_cd_sanity_tests/cmd/ri-exchange/main.go b/ci_cd_sanity_tests/cmd/ri-exchange/main.go index 6272e54f2..cdddb9c54 100644 --- a/ci_cd_sanity_tests/cmd/ri-exchange/main.go +++ b/ci_cd_sanity_tests/cmd/ri-exchange/main.go @@ -13,6 +13,9 @@ import ( "github.com/LeanerCloud/CUDly/pkg/exchange" ) +// Output is the JSON-serialized result written to disk after a quote or +// exchange execution; it captures inputs, the AWS quote, and any error so the +// CI step can archive the artifact and surface a human-readable summary. type Output struct { Quote any `json:"quote"` Mode string `json:"mode"` diff --git a/ci_cd_sanity_tests/pkg/sanity/aws/aws.go b/ci_cd_sanity_tests/pkg/sanity/aws/aws.go index 889b015c4..ad25852c4 100644 --- a/ci_cd_sanity_tests/pkg/sanity/aws/aws.go +++ b/ci_cd_sanity_tests/pkg/sanity/aws/aws.go @@ -1,3 +1,5 @@ +// Package aws implements read-only AWS sanity checks used in CI/CD to verify +// that deploy credentials have sufficient IAM permissions before a real deploy. package aws import ( @@ -14,6 +16,8 @@ import ( "github.com/LeanerCloud/CUDly/ci_cd_sanity_tests/pkg/sanity/report" ) +// Options controls which AWS region to target and optional safety assertions +// applied during the sanity run. type Options struct { Region string ExpectedAccount string // optional safety check @@ -78,6 +82,10 @@ func checkRDS(ctx context.Context, cfg aws.Config, maxList int32) (map[string]st return map[string]string{"db_instances_seen": fmt.Sprintf("%d", len(out.DBInstances))}, nil } +// Run executes all AWS sanity checks in sequence and returns a Report +// summarizing each result. It returns an error only for fatal setup failures +// (credential load, SDK init); individual check failures are captured inside +// the Report so callers can surface them all rather than stopping at the first. func Run(ctx context.Context, opts Options) (*report.Report, error) { if opts.Region == "" { opts.Region = "us-east-1" diff --git a/ci_cd_sanity_tests/pkg/sanity/report/report.go b/ci_cd_sanity_tests/pkg/sanity/report/report.go index 47dbf6e4d..33225ea44 100644 --- a/ci_cd_sanity_tests/pkg/sanity/report/report.go +++ b/ci_cd_sanity_tests/pkg/sanity/report/report.go @@ -1,3 +1,4 @@ +// Package report defines the structured output types for CI/CD sanity-test runs. package report import ( @@ -6,6 +7,7 @@ import ( "time" ) +// Status is the outcome of a single sanity check. type Status string const ( @@ -14,6 +16,8 @@ const ( StatusSkip Status = "SKIP" ) +// CheckResult records the outcome of one named sanity check, including timing +// and optional key/value details for post-hoc debugging. type CheckResult struct { StartedAt time.Time `json:"started_at"` EndedAt time.Time `json:"ended_at"` @@ -23,6 +27,8 @@ type CheckResult struct { Message string `json:"message,omitempty"` } +// Report aggregates the results of a full sanity-test run against a single cloud +// provider and is serialized to JSON for upload to the CI artifact store. type Report struct { RunID string `json:"run_id"` Cloud string `json:"cloud"` @@ -32,10 +38,14 @@ type Report struct { Results []CheckResult `json:"results"` } +// Add appends a single check result to the report. Not safe for concurrent +// use; callers running checks in goroutines must serialize Add calls. func (r *Report) Add(res CheckResult) { r.Results = append(r.Results, res) } +// HasFailures reports whether any recorded check ended in StatusFail. Skips +// and passes do not count as failures. func (r *Report) HasFailures() bool { for _, rr := range r.Results { if rr.Status == StatusFail { @@ -45,6 +55,8 @@ func (r *Report) HasFailures() bool { return false } +// WriteJSON serializes the report to path with indented JSON, using 0600 +// permissions when creating the CI artifact file. func (r *Report) WriteJSON(path string) error { b, err := json.MarshalIndent(r, "", " ") if err != nil { diff --git a/cmd/lambda/clear-rate-limit/main.go b/cmd/lambda/clear-rate-limit/main.go index 2f654a571..ff2ed891b 100644 --- a/cmd/lambda/clear-rate-limit/main.go +++ b/cmd/lambda/clear-rate-limit/main.go @@ -19,6 +19,9 @@ func getDomain() string { return defaultDomain } +// Response is the Lambda function's return value, reporting how many +// forgot_password rate-limit rows were deleted and how many rate-limit +// rows (across all endpoints) remain in the table. type Response struct { Message string `json:"message"` DeletedCount int `json:"deleted_count"` diff --git a/internal/api/types.go b/internal/api/types.go index 48e49b027..bbc3ea92d 100644 --- a/internal/api/types.go +++ b/internal/api/types.go @@ -237,6 +237,7 @@ type LoginRequest struct { MFACode string `json:"mfa_code,omitempty"` } +// LoginResponse carries the JWT token and user summary returned after a successful login. type LoginResponse struct { Token string `json:"token"` ExpiresAt string `json:"expires_at"` @@ -244,6 +245,9 @@ type LoginResponse struct { CSRFToken string `json:"csrf_token,omitempty"` } +// UserInfo is a lightweight projection of the authenticated user included in login +// and session responses; it carries only the fields needed for client-side routing +// and display, without exposing credential hashes or internal audit fields. type UserInfo struct { ID string `json:"id"` Email string `json:"email"` @@ -251,20 +255,28 @@ type UserInfo struct { MFAEnabled bool `json:"mfa_enabled"` } +// SetupAdminRequest is the one-time bootstrap payload used to create the first +// administrator account when the system has no users yet. type SetupAdminRequest struct { Email string `json:"email"` Password string `json:"password"` //nolint:gosec // G117: intentional credential field in request/response struct -- value is supplied by the authenticated caller or returned once at creation; not re-stored downstream } +// PasswordResetRequest initiates a password-reset flow by sending a reset link +// to the provided email address if it matches an existing account. type PasswordResetRequest struct { Email string `json:"email"` } +// PasswordResetConfirm completes a password-reset flow by pairing the one-time +// token (delivered by email) with the user's chosen new password. type PasswordResetConfirm struct { Token string `json:"token"` NewPassword string `json:"new_password"` } +// Session holds the minimal identity claims extracted from a validated JWT and +// attached to the request context by the authentication middleware. type Session struct { UserID string `json:"user_id"` Email string `json:"email"` @@ -276,6 +288,10 @@ type Session struct { UserAPIKeyID string `json:"-"` } +// User is the full user record returned by the admin user-management endpoints. +// It mirrors UserInfo's identity fields and adds CreatedAt/UpdatedAt audit +// timestamps; it is never embedded in the public-facing login or session +// responses, which use the slimmer UserInfo / CurrentUserResponse types instead. type User struct { ID string `json:"id"` Email string `json:"email"`