diff --git a/ci_cd_sanity_tests/cmd/ri-exchange/main.go b/ci_cd_sanity_tests/cmd/ri-exchange/main.go index 6272e54f2..c6eadc90e 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-serialised 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 artefact 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..b9ae277af 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 +// summarising 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..afe22fe88 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 serialised to JSON for upload to the CI artefact 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 serialise 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 serialises the report to path with indented JSON and 0600 +// permissions so it can be uploaded as a CI artefact. 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 e51e2e093..75738c361 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"` diff --git a/providers/azure/services/compute/client.go b/providers/azure/services/compute/client.go index 6ef720dcd..8088098b4 100644 --- a/providers/azure/services/compute/client.go +++ b/providers/azure/services/compute/client.go @@ -170,6 +170,8 @@ type AzureRetailPriceItem struct { Type string `json:"type"` } +// AzureRetailPrice is the paginated response envelope returned by the Azure +// Retail Prices API; NextPageLink is non-empty when additional pages exist. type AzureRetailPrice struct { Items []AzureRetailPriceItem `json:"Items"` NextPageLink string `json:"NextPageLink"`