Help us shape the future of Go! Take the 2026 Go Developer Survey

project

package
v0.28.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package project provides approval workflow management for Prism.

This file implements the approval system introduced in v0.12.0, enabling governance workflows for expensive resources, budget overages, and delegated budget access.

Approval Types:

  • gpu_instance: Required before launching GPU/p*/g* instance types (#149)
  • expensive_instance: Required for instances costing >$2/hr (#149)
  • budget_overage: Required when spending would exceed budget (#157)
  • emergency: Emergency budget increase request (#157)
  • sub_budget: Sub-budget delegation request (#148)

Owner/Admin users bypass approval gates automatically. Member/Viewer users receive HTTP 202 with a request ID when approval is needed.

Package project provides budget and allocation management for v0.5.10+

This file implements the multi-budget system enabling:

  • 1 budget → N projects (single grant funding multiple projects)
  • N budgets → 1 project (multi-source funding)

Package project provides project and budget management functionality for Prism.

This package implements project-based resource organization, budget tracking, and cost controls that enable researchers to organize instances, storage, and costs around research projects with proper financial oversight.

Package project provides monthly budget report generation for Prism.

Reports are delivered as text, CSV, or JSON. PDF output can be generated externally by piping text output through pandoc/wkhtmltopdf.

Usage:

prism budget report my-project --month 2026-02
prism budget report my-project --month 2026-02 --format csv > report.csv

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrDuplicateProjectName is returned when attempting to create a project with a name that already exists
	ErrDuplicateProjectName = errors.New("project name already exists")
)

Error constants

Functions

func ApplyAdjustments added in v0.12.0

func ApplyAdjustments(baseCost float64, adj *CostAdjustments) float64

ApplyAdjustments applies discovered discounts to a cost estimate.

func FormatAdjustmentSummary added in v0.12.0

func FormatAdjustmentSummary(adj *CostAdjustments) string

FormatAdjustmentSummary returns a human-readable summary string.

func SumCreditBalance added in v0.12.0

func SumCreditBalance(credits []AWSCredit) float64

SumCreditBalance returns total remaining credit across all active credits.

func SumMonthlySavings added in v0.12.0

func SumMonthlySavings(discounts []AWSDiscount, monthlySpend float64) (totalSavings float64, effectiveRate float64)

SumMonthlySavings computes total monthly savings from all active discounts given the base monthly spend.

Types

type AWSCredit added in v0.12.0

type AWSCredit struct {
	CreditID           string    `json:"credit_id"`
	Name               string    `json:"name"`
	Description        string    `json:"description"`
	InitialAmount      float64   `json:"initial_amount"`
	RemainingAmount    float64   `json:"remaining_amount"`
	StartDate          time.Time `json:"start_date"`
	ExpirationDate     time.Time `json:"expiration_date"`
	ApplicableServices []string  `json:"applicable_services,omitempty"`
	Active             bool      `json:"active"`
	DaysUntilExpiry    int       `json:"days_until_expiry"`
	ExpiresInWarning   bool      `json:"expires_in_warning"` // true if < 30 days
}

AWSCredit represents a time-limited AWS credit.

func CreditExpiryWarnings added in v0.12.0

func CreditExpiryWarnings(credits []AWSCredit, warnDays int) []AWSCredit

CreditExpiryWarnings returns credits expiring within warnDays days.

type AWSDiscount added in v0.12.0

type AWSDiscount struct {
	DiscountID string     `json:"discount_id"`
	Type       string     `json:"type"` // "EDP" | "PPA"
	Percentage float64    `json:"percentage,omitempty"`
	Services   []string   `json:"services,omitempty"`
	StartDate  time.Time  `json:"start_date"`
	EndDate    *time.Time `json:"end_date,omitempty"`
	Active     bool       `json:"active"`
}

AWSDiscount represents a discovered AWS discount (EDP or PPA).

type ActionExecutor

type ActionExecutor interface {
	// ExecuteHibernateAll hibernates all instances for a project
	ExecuteHibernateAll(projectID string) error
	// ExecuteStopAll stops all instances for a project
	ExecuteStopAll(projectID string) error
	// ExecutePreventLaunch sets a flag to prevent new launches for a project
	ExecutePreventLaunch(projectID string) error
}

ActionExecutor defines the interface for executing budget auto actions

type AddMemberRequest

type AddMemberRequest struct {
	// UserID is the user identifier
	UserID string `json:"user_id"`

	// Role is the project role for the member
	Role types.ProjectRole `json:"role"`

	// AddedBy is who is adding the member
	AddedBy string `json:"added_by"`
}

AddMemberRequest represents a request to add a member to a project

func (*AddMemberRequest) Validate

func (r *AddMemberRequest) Validate() error

Validate validates the add member request

type AlertEvent

type AlertEvent struct {
	Timestamp   time.Time             `json:"timestamp"`
	AlertType   types.BudgetAlertType `json:"alert_type"`
	Threshold   float64               `json:"threshold"`
	SpentAmount float64               `json:"spent_amount"`
	Message     string                `json:"message"`
	Resolved    bool                  `json:"resolved"`
}

AlertEvent represents a budget alert event

type AllocationSummary added in v0.5.10

type AllocationSummary struct {
	// AllocationID is the allocation identifier
	AllocationID string `json:"allocation_id"`

	// BudgetID is the parent budget identifier
	BudgetID string `json:"budget_id"`

	// BudgetName is the parent budget name
	BudgetName string `json:"budget_name"`

	// AllocatedAmount is how much was allocated
	AllocatedAmount float64 `json:"allocated_amount"`

	// SpentAmount is how much has been spent
	SpentAmount float64 `json:"spent_amount"`

	// RemainingAmount is the remaining allocation
	RemainingAmount float64 `json:"remaining_amount"`

	// Utilization is the percentage of allocation spent (0.0-1.0)
	Utilization float64 `json:"utilization"`

	// HasBackup indicates if backup funding is configured
	HasBackup bool `json:"has_backup"`
}

AllocationSummary provides allocation-level information (v0.5.10+ Issue #100)

type ApprovalManager added in v0.12.0

type ApprovalManager struct {
	// contains filtered or unexported fields
}

ApprovalManager handles approval request lifecycle with file-backed persistence

func NewApprovalManager added in v0.12.0

func NewApprovalManager() (*ApprovalManager, error)

NewApprovalManager creates an approval manager persisting to ~/.prism/approvals.json

func (*ApprovalManager) Approve added in v0.12.0

func (am *ApprovalManager) Approve(id, reviewerID, note string) (*ApprovalRequest, error)

Approve marks a request as approved

func (*ApprovalManager) Deny added in v0.12.0

func (am *ApprovalManager) Deny(id, reviewerID, note string) (*ApprovalRequest, error)

Deny marks a request as denied

func (*ApprovalManager) Get added in v0.12.0

func (am *ApprovalManager) Get(id string) (*ApprovalRequest, error)

Get retrieves an approval request by ID

func (*ApprovalManager) List added in v0.12.0

func (am *ApprovalManager) List(projectID string, status ApprovalStatus) ([]*ApprovalRequest, error)

List returns all approval requests, optionally filtered by project and status

func (*ApprovalManager) PruneExpired added in v0.12.0

func (am *ApprovalManager) PruneExpired() (int, error)

PruneExpired marks all pending requests that have passed their ExpiresAt as expired

func (*ApprovalManager) Submit added in v0.12.0

func (am *ApprovalManager) Submit(projectID, requestedBy string, typ ApprovalType, details map[string]interface{}, reason string) (*ApprovalRequest, error)

Submit creates a new pending approval request and returns it

type ApprovalRequest added in v0.12.0

type ApprovalRequest struct {
	// ID is the unique request identifier
	ID string `json:"id"`

	// ProjectID is the project this request is associated with
	ProjectID string `json:"project_id"`

	// RequestedBy is the user who submitted the request
	RequestedBy string `json:"requested_by"`

	// Type is the kind of approval needed
	Type ApprovalType `json:"type"`

	// Status is the current state of the request
	Status ApprovalStatus `json:"status"`

	// Details contains type-specific context (instance_type, amount, etc.)
	Details map[string]interface{} `json:"details"`

	// Reason is the requester's justification
	Reason string `json:"reason"`

	// ReviewedBy is the approver's user ID (empty until reviewed)
	ReviewedBy string `json:"reviewed_by,omitempty"`

	// ReviewNote is an optional note from the approver
	ReviewNote string `json:"review_note,omitempty"`

	// CreatedAt is when the request was submitted
	CreatedAt time.Time `json:"created_at"`

	// ExpiresAt is when the pending request auto-expires (default: 7 days)
	ExpiresAt time.Time `json:"expires_at"`

	// ReviewedAt is when the request was approved or denied
	ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
}

ApprovalRequest is a single governance approval request

type ApprovalStatus added in v0.12.0

type ApprovalStatus string

ApprovalStatus represents the current state of an approval request

const (
	// ApprovalStatusPending indicates the request is awaiting review
	ApprovalStatusPending ApprovalStatus = "pending"

	// ApprovalStatusApproved indicates the request was approved
	ApprovalStatusApproved ApprovalStatus = "approved"

	// ApprovalStatusDenied indicates the request was denied
	ApprovalStatusDenied ApprovalStatus = "denied"

	// ApprovalStatusExpired indicates the request expired before being reviewed
	ApprovalStatusExpired ApprovalStatus = "expired"
)

type ApprovalType added in v0.12.0

type ApprovalType string

ApprovalType identifies the kind of approval being requested

const (
	// ApprovalTypeGPUInstance requires approval before launching GPU/p*/g* instances (#149)
	ApprovalTypeGPUInstance ApprovalType = "gpu_instance"

	// ApprovalTypeExpensiveInstance requires approval for instances >$2/hr (#149)
	ApprovalTypeExpensiveInstance ApprovalType = "expensive_instance"

	// ApprovalTypeBudgetOverage requires approval when spending would exceed budget
	ApprovalTypeBudgetOverage ApprovalType = "budget_overage"

	// ApprovalTypeEmergency requests an emergency budget increase (#157)
	ApprovalTypeEmergency ApprovalType = "emergency"

	// ApprovalTypeSubBudget requests sub-budget delegation from PI to member (#148)
	ApprovalTypeSubBudget ApprovalType = "sub_budget"
)

type BudgetManager added in v0.5.10

type BudgetManager struct {
	// contains filtered or unexported fields
}

BudgetManager handles budget pools and project allocations

func NewBudgetManager added in v0.5.10

func NewBudgetManager() (*BudgetManager, error)

NewBudgetManager creates a new budget manager

func (*BudgetManager) ActivateBackupFunding added in v0.5.10

func (bm *BudgetManager) ActivateBackupFunding(ctx context.Context, projectID string, primaryAllocationID string, backupAllocationID string) error

ActivateBackupFunding switches a project to its backup funding allocation This is called when the primary allocation is exhausted and backup exists

func (*BudgetManager) CheckAllocationStatus added in v0.5.10

func (bm *BudgetManager) CheckAllocationStatus(ctx context.Context, allocationID string) (exhausted bool, remaining float64, err error)

CheckAllocationStatus checks if an allocation is exhausted or nearing exhaustion

func (*BudgetManager) Close added in v0.5.10

func (bm *BudgetManager) Close() error

Close cleanly shuts down the budget manager

func (*BudgetManager) CreateAllocation added in v0.5.10

CreateAllocation creates a new project budget allocation

func (*BudgetManager) CreateBudget added in v0.5.10

func (bm *BudgetManager) CreateBudget(ctx context.Context, req *CreateBudgetRequest) (*types.Budget, error)

CreateBudget creates a new budget pool

func (*BudgetManager) DeleteAllocation added in v0.5.10

func (bm *BudgetManager) DeleteAllocation(ctx context.Context, allocationID string) error

DeleteAllocation removes an allocation

func (*BudgetManager) DeleteBudget added in v0.5.10

func (bm *BudgetManager) DeleteBudget(ctx context.Context, budgetID string) error

DeleteBudget removes a budget and all associated allocations

func (*BudgetManager) GenerateBudgetRollupReport added in v0.5.10

func (bm *BudgetManager) GenerateBudgetRollupReport(ctx context.Context) (*BudgetRollupReport, error)

GenerateBudgetRollupReport generates a comprehensive rollup report across all budgets (v0.5.10+ Issue #100)

func (*BudgetManager) GetAllocation added in v0.5.10

func (bm *BudgetManager) GetAllocation(ctx context.Context, allocationID string) (*types.ProjectBudgetAllocation, error)

GetAllocation retrieves an allocation by ID

func (*BudgetManager) GetBudget added in v0.5.10

func (bm *BudgetManager) GetBudget(ctx context.Context, budgetID string) (*types.Budget, error)

GetBudget retrieves a budget by ID

func (*BudgetManager) GetBudgetAllocations added in v0.5.10

func (bm *BudgetManager) GetBudgetAllocations(ctx context.Context, budgetID string) ([]*types.ProjectBudgetAllocation, error)

GetBudgetAllocations retrieves all allocations for a budget

func (*BudgetManager) GetBudgetByName added in v0.5.10

func (bm *BudgetManager) GetBudgetByName(ctx context.Context, name string) (*types.Budget, error)

GetBudgetByName retrieves a budget by name

func (*BudgetManager) GetBudgetReallocationHistory added in v0.5.10

func (bm *BudgetManager) GetBudgetReallocationHistory(ctx context.Context, budgetID string) ([]*ReallocationRecord, error)

GetBudgetReallocationHistory retrieves all reallocations for a budget (v0.5.10+ Issue #99)

func (*BudgetManager) GetBudgetSummary added in v0.5.10

func (bm *BudgetManager) GetBudgetSummary(ctx context.Context, budgetID string) (*types.BudgetSummary, error)

GetBudgetSummary generates a summary view of a budget

func (*BudgetManager) GetBudgetSummaryReport added in v0.5.10

func (bm *BudgetManager) GetBudgetSummaryReport(ctx context.Context, budgetID string) (*BudgetSummaryReport, error)

GetBudgetSummaryReport generates a detailed summary for a specific budget (v0.5.10+ Issue #100)

func (*BudgetManager) GetProjectAllocations added in v0.5.10

func (bm *BudgetManager) GetProjectAllocations(ctx context.Context, projectID string) ([]*types.ProjectBudgetAllocation, error)

GetProjectAllocations retrieves all allocations for a project

func (*BudgetManager) GetProjectCostRollup added in v0.5.10

func (bm *BudgetManager) GetProjectCostRollup(ctx context.Context, projectIDs []string) ([]ProjectCostSummary, error)

GetProjectCostRollup generates cost rollup for specific projects (v0.5.10+ Issue #100)

func (*BudgetManager) GetProjectFundingSummary added in v0.5.10

func (bm *BudgetManager) GetProjectFundingSummary(ctx context.Context, projectID string) (*types.ProjectFundingSummary, error)

GetProjectFundingSummary generates a summary view of all funding for a project

func (*BudgetManager) GetReallocationHistory added in v0.5.10

func (bm *BudgetManager) GetReallocationHistory(ctx context.Context, allocationID string) ([]*ReallocationRecord, error)

GetReallocationHistory retrieves reallocation history for a specific allocation (v0.5.10+ Issue #99)

func (*BudgetManager) ListBudgets added in v0.5.10

func (bm *BudgetManager) ListBudgets(ctx context.Context) ([]*types.Budget, error)

ListBudgets retrieves all budgets

func (*BudgetManager) ReallocateFunds added in v0.5.10

func (bm *BudgetManager) ReallocateFunds(ctx context.Context, req *ReallocateFundsRequest) (*ReallocationRecord, error)

ReallocateFunds moves funds between allocations atomically (v0.5.10+ Issue #99)

func (*BudgetManager) RecordSpending added in v0.5.10

func (bm *BudgetManager) RecordSpending(ctx context.Context, allocationID string, amount float64) (*SpendingResult, error)

RecordSpending records spending against an allocation with backup funding support (v0.5.10+) Returns SpendingResult indicating if backup was activated

func (*BudgetManager) SetProjectManager added in v0.26.0

func (bm *BudgetManager) SetProjectManager(m *Manager)

SetProjectManager injects a project manager so GetBudgetSummary and GetProjectFundingSummary can populate project names and default allocation IDs.

func (*BudgetManager) UpdateAllocation added in v0.5.10

func (bm *BudgetManager) UpdateAllocation(ctx context.Context, allocationID string, req *UpdateAllocationRequest) (*types.ProjectBudgetAllocation, error)

UpdateAllocation updates an existing allocation

func (*BudgetManager) UpdateBudget added in v0.5.10

func (bm *BudgetManager) UpdateBudget(ctx context.Context, budgetID string, req *UpdateBudgetRequest) (*types.Budget, error)

UpdateBudget updates an existing budget

type BudgetPredictor added in v0.11.0

type BudgetPredictor struct {
	// contains filtered or unexported fields
}

BudgetPredictor uses cost history to forecast future spending.

func NewBudgetPredictor added in v0.11.0

func NewBudgetPredictor() *BudgetPredictor

NewBudgetPredictor creates a new predictor with default calculators.

func (*BudgetPredictor) Predict added in v0.11.0

func (p *BudgetPredictor) Predict(
	projectID string,
	history []CostDataPoint,
	budget *types.ProjectBudget,
	months int,
	grantRenewalDate *time.Time,
) (*ShortfallPrediction, error)

Predict performs forward projection using linear regression on recent cost history.

months is the number of future months to forecast. grantRenewalDate may be nil.

type BudgetRollupReport added in v0.5.10

type BudgetRollupReport struct {
	// ReportID is a unique identifier for this report
	ReportID string `json:"report_id"`

	// GeneratedAt is when this report was generated
	GeneratedAt time.Time `json:"generated_at"`

	// BudgetSummaries provides per-budget rollup information
	BudgetSummaries []BudgetSummaryReport `json:"budget_summaries"`

	// TotalBudgets is the total number of budgets in the report
	TotalBudgets int `json:"total_budgets"`

	// TotalAllocated is the sum of all budget allocations
	TotalAllocated float64 `json:"total_allocated"`

	// TotalSpent is the sum of all spending across all budgets
	TotalSpent float64 `json:"total_spent"`

	// TotalRemaining is the total remaining across all budgets
	TotalRemaining float64 `json:"total_remaining"`

	// OverallUtilization is the percentage of total budget utilized (0.0-1.0)
	OverallUtilization float64 `json:"overall_utilization"`

	// ProjectCount is the total number of projects funded
	ProjectCount int `json:"project_count"`
}

BudgetRollupReport provides aggregated cost and budget information (v0.5.10+ Issue #100)

type BudgetStatus

type BudgetStatus struct {
	// ProjectID is the project identifier
	ProjectID string `json:"project_id"`

	// BudgetEnabled indicates if budget tracking is enabled
	BudgetEnabled bool `json:"budget_enabled"`

	// TotalBudget is the total project budget
	TotalBudget float64 `json:"total_budget"`

	// SpentAmount is the current amount spent
	SpentAmount float64 `json:"spent_amount"`

	// RemainingBudget is the remaining budget
	RemainingBudget float64 `json:"remaining_budget"`

	// SpentPercentage is the percentage of budget spent (0.0-1.0)
	SpentPercentage float64 `json:"spent_percentage"`

	// ProjectedMonthlySpend is the projected monthly spending based on current usage
	ProjectedMonthlySpend float64 `json:"projected_monthly_spend"`

	// DaysUntilBudgetExhausted estimates when budget will be exhausted at current rate
	DaysUntilBudgetExhausted *int `json:"days_until_exhausted,omitempty"`

	// BurnRate contains period-aware burn rate analysis (nil when history is insufficient).
	BurnRate *BurnRateInfo `json:"burn_rate,omitempty"`

	// Surplus contains banking and carry-over information (nil for project-lifetime budgets).
	Surplus *SurplusInfo `json:"surplus,omitempty"`

	// ActiveAlerts are currently active budget alerts
	ActiveAlerts []string `json:"active_alerts"`

	// TriggeredActions are actions that have been triggered
	TriggeredActions []string `json:"triggered_actions"`

	// LastUpdated is when this status was calculated
	LastUpdated time.Time `json:"last_updated"`
}

BudgetStatus represents the current budget status of a project

type BudgetStatusSummary

type BudgetStatusSummary struct {
	// TotalBudget is the total project budget
	TotalBudget float64 `json:"total_budget"`

	// SpentAmount is the current amount spent
	SpentAmount float64 `json:"spent_amount"`

	// SpentPercentage is the percentage of budget spent (0.0-1.0)
	SpentPercentage float64 `json:"spent_percentage"`

	// AlertCount is the number of active alerts
	AlertCount int `json:"alert_count"`
}

BudgetStatusSummary provides a condensed view of budget status

type BudgetSummaryReport added in v0.5.10

type BudgetSummaryReport struct {
	// BudgetID is the budget identifier
	BudgetID string `json:"budget_id"`

	// BudgetName is the budget name
	BudgetName string `json:"budget_name"`

	// Period is the budget period
	Period string `json:"period"`

	// TotalAmount is the total budget amount
	TotalAmount float64 `json:"total_amount"`

	// AllocatedAmount is how much has been allocated to projects
	AllocatedAmount float64 `json:"allocated_amount"`

	// SpentAmount is how much has been spent
	SpentAmount float64 `json:"spent_amount"`

	// RemainingAmount is the remaining unspent budget
	RemainingAmount float64 `json:"remaining_amount"`

	// Utilization is the percentage of budget utilized (0.0-1.0)
	Utilization float64 `json:"utilization"`

	// ProjectCount is the number of projects funded by this budget
	ProjectCount int `json:"project_count"`

	// AllocationCount is the number of allocations from this budget
	AllocationCount int `json:"allocation_count"`

	// Projects provides per-project information
	Projects []ProjectCostSummary `json:"projects"`
}

BudgetSummaryReport provides detailed budget information (v0.5.10+ Issue #100)

type BudgetTracker

type BudgetTracker struct {
	// contains filtered or unexported fields
}

BudgetTracker handles budget tracking and cost analysis for projects

func NewBudgetTracker

func NewBudgetTracker() (*BudgetTracker, error)

NewBudgetTracker creates a new budget tracker

func (*BudgetTracker) CheckBudgetStatus

func (bt *BudgetTracker) CheckBudgetStatus(projectID string) (*BudgetStatus, error)

CheckBudgetStatus checks the current budget status and returns detailed information

func (*BudgetTracker) Close

func (bt *BudgetTracker) Close() error

Close cleanly shuts down the budget tracker

func (*BudgetTracker) GetAllProjectIDs

func (bt *BudgetTracker) GetAllProjectIDs() []string

GetCostTrends returns cost trends for a project over a specified period GetAllProjectIDs returns all project IDs being tracked

func (*BudgetTracker) GetBudgetStatus

func (bt *BudgetTracker) GetBudgetStatus(projectID string) (map[string]interface{}, error)

GetBudgetStatus returns the current budget status for a project

func (*BudgetTracker) GetCostBreakdown

func (bt *BudgetTracker) GetCostBreakdown(projectID string, startDate, endDate time.Time) (*types.ProjectCostBreakdown, error)

GetCostBreakdown retrieves detailed cost analysis for a project

func (*BudgetTracker) GetCostHistory added in v0.11.0

func (bt *BudgetTracker) GetCostHistory(projectID string) ([]CostDataPoint, error)

GetCostHistory returns the full cost history for a project. Used by BudgetPredictor for forecasting.

func (*BudgetTracker) GetCostTrends

func (bt *BudgetTracker) GetCostTrends(projectID string, period string) (map[string]interface{}, error)

func (*BudgetTracker) GetCurrentMonthlyRate added in v0.6.0

func (bt *BudgetTracker) GetCurrentMonthlyRate(projectID string) float64

GetCurrentMonthlyRate calculates the current monthly spending rate for a project This is a simplified implementation for Issue #326

func (*BudgetTracker) GetProjectCostHistory

func (bt *BudgetTracker) GetProjectCostHistory(projectID string, days int) ([]float64, error)

GetProjectCostHistory returns cost history for a project

func (*BudgetTracker) GetResourceUsage

func (bt *BudgetTracker) GetResourceUsage(projectID string, period time.Duration) (*types.ProjectResourceUsage, error)

GetResourceUsage retrieves resource utilization metrics for a project

func (*BudgetTracker) InitializeProject

func (bt *BudgetTracker) InitializeProject(projectID string, budget *types.ProjectBudget) error

InitializeProject initializes budget tracking for a new project

func (*BudgetTracker) RemoveProject

func (bt *BudgetTracker) RemoveProject(projectID string) error

RemoveProject removes budget tracking for a project

func (*BudgetTracker) SetActionExecutor

func (bt *BudgetTracker) SetActionExecutor(executor ActionExecutor)

SetActionExecutor sets the action executor for budget auto actions

func (*BudgetTracker) SetAlerter added in v0.12.0

func (bt *BudgetTracker) SetAlerter(d alerting.AlertDispatcher)

SetAlerter configures the AlertDispatcher used for budget threshold notifications. Defaults to LogDispatcher if not called.

func (*BudgetTracker) UpdateProjectCosts

func (bt *BudgetTracker) UpdateProjectCosts(projectID string, instances []types.Instance, storageVolumes []types.StorageVolume) error

UpdateProjectCosts updates cost tracking for a project

func (*BudgetTracker) UpdateProjectSpending

func (bt *BudgetTracker) UpdateProjectSpending(projectID string, instanceCosts []types.InstanceCost, storageCosts []types.StorageCost) error

UpdateProjectSpending updates project spending with instance and storage costs

type BurnRateCalculator added in v0.11.0

type BurnRateCalculator struct{}

BurnRateCalculator computes time-bounded spending rates.

func (*BurnRateCalculator) BurnRateVsAllocation added in v0.11.0

func (b *BurnRateCalculator) BurnRateVsAllocation(history []CostDataPoint, window PeriodWindow, totalAllocation float64) (float64, float64, float64)

BurnRateVsAllocation compares the current daily burn rate to the pro-rated daily allocation for the current period.

Returns (actualDailyRate, expectedDailyRate, ratio) where ratio > 1.0 means spending faster than the period allocation allows.

func (*BurnRateCalculator) ComputeBurnRate added in v0.11.0

func (b *BurnRateCalculator) ComputeBurnRate(
	history []CostDataPoint,
	period types.BudgetPeriod,
	startDate time.Time,
	totalAllocation float64,
) *BurnRateInfo

ComputeBurnRate builds a fully populated BurnRateInfo for a project budget.

func (*BurnRateCalculator) CurrentPeriodWindow added in v0.11.0

func (b *BurnRateCalculator) CurrentPeriodWindow(period types.BudgetPeriod, startDate time.Time) PeriodWindow

CurrentPeriodWindow calculates the current period window given a BudgetPeriod and the date from which the project started being tracked.

func (*BurnRateCalculator) DailyBurnRate added in v0.11.0

func (b *BurnRateCalculator) DailyBurnRate(history []CostDataPoint, windowDays int) float64

DailyBurnRate returns dollars/day averaged over up to windowDays of history.

func (*BurnRateCalculator) PeriodSpend added in v0.11.0

func (b *BurnRateCalculator) PeriodSpend(history []CostDataPoint, window PeriodWindow) float64

PeriodSpend returns the total cost delta within the given window.

func (*BurnRateCalculator) WeeklyBurnRate added in v0.11.0

func (b *BurnRateCalculator) WeeklyBurnRate(history []CostDataPoint) float64

WeeklyBurnRate returns projected weekly spend.

type BurnRateInfo added in v0.11.0

type BurnRateInfo struct {
	// DailyRate is the 7-day trailing average spend in dollars per day.
	DailyRate float64 `json:"daily_rate"`
	// WeeklyRate is projected weekly spend.
	WeeklyRate float64 `json:"weekly_rate"`
	// MonthlyRate is projected monthly spend.
	MonthlyRate float64 `json:"monthly_rate"`
	// PeriodAllocation is the budget amount for the current window.
	PeriodAllocation float64 `json:"period_allocation"`
	// PeriodSpend is how much has been spent within the current window.
	PeriodSpend float64 `json:"period_spend"`
	// PeriodRemaining is how much of the period allocation is left.
	PeriodRemaining float64 `json:"period_remaining"`
	// BurnRateRatio is actual/expected rate; >1.0 means over-paced.
	BurnRateRatio float64 `json:"burn_rate_ratio"`
	// PaceStatus characterises the current spending pace.
	PaceStatus PaceStatus `json:"pace_status"`
	// Window is the current period window.
	Window PeriodWindow `json:"window"`
}

BurnRateInfo contains period-aware burn rate analysis.

type CostAdjustments added in v0.12.0

type CostAdjustments struct {
	ProjectID           string        `json:"project_id"`
	Discounts           []AWSDiscount `json:"discounts"`
	Credits             []AWSCredit   `json:"credits"`
	TotalMonthlySavings float64       `json:"total_monthly_savings"`
	TotalCreditBalance  float64       `json:"total_credit_balance"`
	EffectiveCostRate   float64       `json:"effective_cost_rate"` // 0.90 = 10% discount
	UpdatedAt           time.Time     `json:"updated_at"`
}

CostAdjustments summarizes all active discounts and credits for a project.

func MockDiscovery added in v0.12.0

func MockDiscovery(projectID string) *CostAdjustments

MockDiscovery returns simulated discounts and credits for environments without Cost Explorer access. Used as a fallback.

type CostCalculator

type CostCalculator struct {
}

CostCalculator calculates AWS costs for instances and storage

func (*CostCalculator) ApplyDiscount added in v0.11.0

func (c *CostCalculator) ApplyDiscount(baseCost float64, config *types.DiscountConfig, serviceType string) float64

ApplyDiscount applies a DiscountConfig to a base cost for a given service type. serviceType should be one of: "ec2", "ebs", "efs", "s3".

func (*CostCalculator) CalculateEBSCost added in v0.11.0

func (c *CostCalculator) CalculateEBSCost(spec EBSVolumeSpec) EBSCostDetail

CalculateEBSCost returns a detailed cost breakdown for a single EBS volume.

func (*CostCalculator) CalculateEFSCost added in v0.11.0

func (c *CostCalculator) CalculateEFSCost(spec EFSVolumeSpec) EFSCostDetail

CalculateEFSCost returns a detailed cost breakdown for a single EFS filesystem.

func (*CostCalculator) CalculateInstanceCosts

func (c *CostCalculator) CalculateInstanceCosts(instances []types.Instance) ([]types.InstanceCost, float64)

CalculateInstanceCosts calculates costs for a list of instances

func (*CostCalculator) CalculateS3Cost added in v0.11.0

func (c *CostCalculator) CalculateS3Cost(spec S3CostSpec) S3CostDetail

CalculateS3Cost returns a detailed cost breakdown for a single S3 bucket.

func (*CostCalculator) CalculateStorageCosts

func (c *CostCalculator) CalculateStorageCosts(storageVolumes []types.StorageVolume) ([]types.StorageCost, float64)

CalculateStorageCosts calculates costs for all storage volumes

func (*CostCalculator) EstimateHibernationSavings

func (c *CostCalculator) EstimateHibernationSavings(instanceType string, hibernatedHours float64) float64

EstimateHibernationSavings estimates the cost savings from hibernating vs running

func (*CostCalculator) EstimateMonthlyCost

func (c *CostCalculator) EstimateMonthlyCost(instanceType string, storageGB int) float64

EstimateMonthlyCost estimates the monthly cost for running an instance continuously

func (*CostCalculator) GetInstanceHourlyRate

func (c *CostCalculator) GetInstanceHourlyRate(instanceType string) float64

GetInstanceHourlyRate returns the hourly rate for an instance type

func (*CostCalculator) GetStorageMonthlyRate

func (c *CostCalculator) GetStorageMonthlyRate(storageType string) float64

GetStorageMonthlyRate returns the monthly rate per GB for a storage type

type CostDataPoint

type CostDataPoint struct {
	Timestamp     time.Time            `json:"timestamp"`
	TotalCost     float64              `json:"total_cost"`
	InstanceCosts []types.InstanceCost `json:"instance_costs"`
	StorageCosts  []types.StorageCost  `json:"storage_costs"`
	DailyCost     float64              `json:"daily_cost"`
}

CostDataPoint represents a point-in-time cost measurement

type CreateAllocationRequest added in v0.5.10

type CreateAllocationRequest struct {
	// BudgetID is the parent budget pool
	BudgetID string `json:"budget_id"`

	// ProjectID is the project receiving the allocation
	ProjectID string `json:"project_id"`

	// AllocatedAmount is how much of the budget to allocate to this project
	AllocatedAmount float64 `json:"allocated_amount"`

	// AlertThreshold is an optional project-specific alert threshold (overrides budget default)
	AlertThreshold *float64 `json:"alert_threshold,omitempty"`

	// BackupAllocationID is an optional backup funding source for exhaustion (#234)
	BackupAllocationID *string `json:"backup_allocation_id,omitempty"`

	// Notes provide context for this allocation
	Notes string `json:"notes,omitempty"`

	// AllocatedBy is the user who created the allocation
	AllocatedBy string `json:"allocated_by"`
}

CreateAllocationRequest represents a request to allocate budget to a project

func (*CreateAllocationRequest) Validate added in v0.5.10

func (r *CreateAllocationRequest) Validate() error

Validate validates the create allocation request

type CreateBudgetRequest

type CreateBudgetRequest struct {
	// Name is the budget name (e.g., "NSF Grant CISE-2024-12345")
	Name string `json:"name"`

	// Description provides budget details
	Description string `json:"description"`

	// TotalAmount is the total budget pool in USD
	TotalAmount float64 `json:"total_amount"`

	// Period defines the budget period
	Period types.BudgetPeriod `json:"period"`

	// StartDate is when the budget period began
	StartDate time.Time `json:"start_date"`

	// EndDate is when the budget period ends (optional for ongoing budgets)
	EndDate *time.Time `json:"end_date,omitempty"`

	// AlertThreshold is the global alert percentage (0.0-1.0)
	AlertThreshold float64 `json:"alert_threshold"`

	// CreatedBy is the user who created the budget
	CreatedBy string `json:"created_by"`

	// Tags for budget organization
	Tags map[string]string `json:"tags,omitempty"`
}

CreateBudgetRequest represents a request to create a budget pool (v0.5.10+)

func (*CreateBudgetRequest) Validate

func (r *CreateBudgetRequest) Validate() error

Validate validates the create budget request

type CreateProjectBudgetRequest added in v0.5.10

type CreateProjectBudgetRequest struct {
	// TotalBudget is the total project budget in USD
	TotalBudget float64 `json:"total_budget"`

	// MonthlyLimit is the optional monthly spending limit in USD
	MonthlyLimit *float64 `json:"monthly_limit,omitempty"`

	// DailyLimit is the optional daily spending limit in USD
	DailyLimit *float64 `json:"daily_limit,omitempty"`

	// AlertThresholds define when to send budget alerts
	AlertThresholds []types.BudgetAlert `json:"alert_thresholds,omitempty"`

	// AutoActions define automatic actions when thresholds are reached
	AutoActions []types.BudgetAutoAction `json:"auto_actions,omitempty"`

	// BudgetPeriod defines the budget period
	BudgetPeriod types.BudgetPeriod `json:"budget_period"`

	// EndDate is when the budget period ends (optional)
	EndDate *time.Time `json:"end_date,omitempty"`
}

CreateProjectBudgetRequest represents a request to create a project budget (DEPRECATED in v0.5.10) Use CreateBudgetRequest + CreateAllocationRequest instead

func (*CreateProjectBudgetRequest) Validate added in v0.5.10

func (r *CreateProjectBudgetRequest) Validate() error

Validate validates the create project budget request (DEPRECATED in v0.5.10)

type CreateProjectRequest

type CreateProjectRequest struct {
	// Name is the project name (required)
	Name string `json:"name"`

	// Description provides project details
	Description string `json:"description"`

	// Owner is the project owner/principal investigator
	Owner string `json:"owner"`

	// Tags for project organization
	Tags map[string]string `json:"tags,omitempty"`

	// Budget contains optional budget configuration (DEPRECATED in v0.5.10)
	// Use Budget/Allocation system instead
	Budget *CreateProjectBudgetRequest `json:"budget,omitempty"`
}

CreateProjectRequest represents a request to create a new project

func (*CreateProjectRequest) Validate

func (r *CreateProjectRequest) Validate() error

Validate validates the create project request

type CushionConfig added in v0.11.0

type CushionConfig struct {
	// Enabled activates the cushion system.
	Enabled bool `json:"enabled"`
	// HeadroomPercent is the fractional budget headroom (e.g. 0.10 = 10%).
	// Ignored when HeadroomFixed is set.
	HeadroomPercent float64 `json:"headroom_percent"`
	// HeadroomFixed is a fixed-dollar headroom amount (takes precedence over HeadroomPercent).
	HeadroomFixed *float64 `json:"headroom_fixed_usd,omitempty"`
	// Mode controls what action is taken when the cushion threshold is crossed.
	Mode CushionMode `json:"mode"`
	// NotifyBeforeAction sends a warning alert before taking the configured action.
	NotifyBeforeAction bool `json:"notify_before_action"`
	// WarnLeadHours is how many hours before the projected action to send the warning.
	WarnLeadHours int `json:"warn_lead_hours"`
}

CushionConfig defines the automatic safety headroom for a project budget.

type CushionEvaluator added in v0.11.0

type CushionEvaluator struct {
	// contains filtered or unexported fields
}

CushionEvaluator evaluates and executes budget cushion actions.

func NewCushionEvaluator added in v0.11.0

func NewCushionEvaluator(executor ActionExecutor, alerter alerting.AlertDispatcher) *CushionEvaluator

NewCushionEvaluator creates a CushionEvaluator.

func (*CushionEvaluator) Evaluate added in v0.11.0

func (ce *CushionEvaluator) Evaluate(status *BudgetStatus, config CushionConfig) CushionStatus

Evaluate checks whether the cushion threshold has been crossed.

Returns the cushion status. Call Execute if status.Triggered is true.

func (*CushionEvaluator) Execute added in v0.11.0

func (ce *CushionEvaluator) Execute(ctx context.Context, projectID, projectName string, config CushionConfig, status BudgetStatus) error

Execute runs the configured cushion action for the given project.

type CushionMode added in v0.11.0

type CushionMode string

CushionMode defines the action taken when the budget headroom threshold is crossed.

const (
	// CushionModeHibernate hibernates all running instances for the project.
	CushionModeHibernate CushionMode = "hibernate"
	// CushionModeStop stops all running instances (no resume).
	CushionModeStop CushionMode = "stop"
	// CushionModePreventLaunch blocks new instance launches without stopping running ones.
	CushionModePreventLaunch CushionMode = "prevent_launch"
	// CushionModeNotifyOnly sends an alert but takes no automated action.
	CushionModeNotifyOnly CushionMode = "notify_only"
)

type CushionStatus added in v0.11.0

type CushionStatus struct {
	// Triggered is true when the remaining budget is at or below the headroom.
	Triggered bool `json:"triggered"`
	// Headroom is the configured dollar headroom.
	Headroom float64 `json:"headroom"`
	// Remaining is the actual remaining budget.
	Remaining float64 `json:"remaining"`
	// Message is a human-readable status description.
	Message string `json:"message"`
}

CushionStatus describes whether the cushion threshold has been reached.

type DiscoveryResult added in v0.12.0

type DiscoveryResult struct {
	Discounts []AWSDiscount
	Credits   []AWSCredit
	Error     error
}

DiscoveryResult is what the discovery process returns.

type EBSCostDetail added in v0.11.0

type EBSCostDetail struct {
	VolumeName       string  `json:"volume_name"`
	VolumeID         string  `json:"volume_id"`
	VolumeType       string  `json:"volume_type"`
	SizeGB           float64 `json:"size_gb"`
	StorageCost      float64 `json:"storage_cost"`       // base GB × monthly rate
	IOPSCost         float64 `json:"iops_cost"`          // io1/io2 provisioned IOPS
	ThroughputCost   float64 `json:"throughput_cost"`    // gp3 throughput above baseline
	TotalMonthlyCost float64 `json:"total_monthly_cost"` // pro-rated to this month
	AgeHours         float64 `json:"age_hours"`
	Region           string  `json:"region"`
}

EBSCostDetail is the output struct for a single EBS volume cost breakdown.

type EBSVolumeSpec added in v0.11.0

type EBSVolumeSpec struct {
	VolumeID   string
	Name       string
	SizeGB     int32
	VolumeType string // gp3, gp2, io1, io2, st1, sc1
	IOPS       int32  // provisioned IOPS (io1/io2 only)
	Throughput int32  // provisioned MB/s above baseline (gp3 only)
	Region     string
	AgeSeconds float64 // seconds since creation, for pro-rating
}

EBSVolumeSpec contains configuration needed for accurate EBS pricing.

type EFSCostDetail added in v0.11.0

type EFSCostDetail struct {
	FilesystemName        string  `json:"filesystem_name"`
	FilesystemID          string  `json:"filesystem_id"`
	StandardStorageGB     float64 `json:"standard_storage_gb"`
	IAStorageGB           float64 `json:"ia_storage_gb"`
	StandardStorageCost   float64 `json:"standard_storage_cost"`
	IAStorageCost         float64 `json:"ia_storage_cost"`
	ThroughputMode        string  `json:"throughput_mode"`
	ProvisionedThroughput float64 `json:"provisioned_throughput_mbps"`
	ThroughputCost        float64 `json:"throughput_cost"`
	TotalMonthlyCost      float64 `json:"total_monthly_cost"`
	Region                string  `json:"region"`
}

EFSCostDetail is the output struct for a single EFS filesystem cost breakdown.

type EFSVolumeSpec added in v0.11.0

type EFSVolumeSpec struct {
	FilesystemID      string
	Name              string
	SizeBytesStandard int64   // bytes in Standard storage class
	SizeBytesIA       int64   // bytes in Infrequent Access storage class
	ThroughputMode    string  // "bursting" | "provisioned" | "elastic"
	ProvisionedMBps   float64 // only for provisioned mode
	ElasticReadGB     float64 // GB transferred (elastic mode reads this month)
	ElasticWriteGB    float64 // GB transferred (elastic mode writes this month)
	Region            string
	AgeSeconds        float64
}

EFSVolumeSpec contains configuration needed for accurate EFS pricing.

type ForecastDataPoint added in v0.6.0

type ForecastDataPoint struct {
	// Month is the month for this data point (YYYY-MM format)
	Month string `json:"month"`

	// ProjectedCost is the projected spending for this month
	ProjectedCost float64 `json:"projected_cost"`

	// CumulativeCost is the cumulative cost to date
	CumulativeCost float64 `json:"cumulative_cost"`

	// ActualCost is the actual cost (for historical data only)
	ActualCost *float64 `json:"actual_cost,omitempty"`
}

ForecastDataPoint represents a single month's forecast

type ForecastMonth added in v0.11.0

type ForecastMonth struct {
	Month           string   `json:"month"` // "2026-04"
	ProjectedSpend  float64  `json:"projected_spend"`
	CumulativeSpend float64  `json:"cumulative_spend"`
	RemainingBudget float64  `json:"remaining_budget"`
	IsProjected     bool     `json:"is_projected"` // false for historical months
	ActualSpend     *float64 `json:"actual_spend,omitempty"`
}

ForecastMonth is a per-month spending projection.

type GDEWStatus added in v0.12.0

type GDEWStatus struct {
	ProjectID        string    `json:"project_id"`
	MonthStart       time.Time `json:"month_start"`
	MonthEnd         time.Time `json:"month_end"`
	TotalSpendMTD    float64   `json:"total_spend_mtd"`
	EgressChargesMTD float64   `json:"egress_charges_mtd"`
	AvailableCredit  float64   `json:"available_credit"` // 15% of total spend
	UsedCredit       float64   `json:"used_credit"`      // min(egress, available)
	RemainingCredit  float64   `json:"remaining_credit"`
	NetEgressCost    float64   `json:"net_egress_cost"`
	CoveragePercent  float64   `json:"coverage_percent"` // used/egress * 100
	FullyCovered     bool      `json:"fully_covered"`
	NearingLimit     bool      `json:"nearing_limit"` // remaining < $20
	StatusMessage    string    `json:"status_message"`
	LastCalculated   time.Time `json:"last_calculated"`
}

GDEWStatus represents the current GDEW credit status for a project.

type GDEWTracker added in v0.12.0

type GDEWTracker struct {
	// contains filtered or unexported fields
}

GDEWTracker computes AWS Global Data Egress Waiver credits. GDEW provides credits up to 15% of total monthly AWS spend against egress charges.

func NewGDEWTracker added in v0.12.0

func NewGDEWTracker() *GDEWTracker

NewGDEWTracker creates a new GDEWTracker.

func (*GDEWTracker) Get added in v0.12.0

func (g *GDEWTracker) Get(projectID string) *GDEWStatus

Get returns the current GDEW status for a project, or nil if not tracked.

func (*GDEWTracker) Update added in v0.12.0

func (g *GDEWTracker) Update(projectID string, totalSpendMTD, egressChargesMTD float64) *GDEWStatus

Update recalculates GDEW status for a project given current month spend and egress.

type GrantRenewalAlert added in v0.11.0

type GrantRenewalAlert struct {
	RenewalDate       time.Time `json:"renewal_date"`
	DaysBeforeRenewal int       `json:"days_before_renewal"` // exhaustion N days before renewal
	ShortfallAmount   float64   `json:"shortfall_amount"`
	Message           string    `json:"message"`
}

GrantRenewalAlert fires when budget exhaustion is predicted before a grant renewal date.

type InstanceSpendLine added in v0.12.0

type InstanceSpendLine struct {
	InstanceName string  `json:"instance_name"`
	InstanceType string  `json:"instance_type"`
	RunningHours float64 `json:"running_hours"`
	ComputeCost  float64 `json:"compute_cost"`
	StorageCost  float64 `json:"storage_cost"`
	TotalCost    float64 `json:"total_cost"`
}

InstanceSpendLine is a single instance row in a monthly report

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager handles project lifecycle, budget tracking, and cost controls

func NewManager

func NewManager() (*Manager, error)

NewManager creates a new project manager

func (*Manager) AddProjectMember

func (m *Manager) AddProjectMember(ctx context.Context, projectID string, member *types.ProjectMember) error

AddProjectMember adds a member to a project

func (*Manager) AllowLaunches

func (m *Manager) AllowLaunches(ctx context.Context, projectID string) error

AllowLaunches allows new instance launches for a project (clears launch prevention)

func (*Manager) CheckBudgetStatus

func (m *Manager) CheckBudgetStatus(ctx context.Context, projectID string) (*BudgetStatus, error)

CheckBudgetStatus checks the current budget status and triggers alerts if needed

func (*Manager) CheckGrantPeriods added in v0.12.0

func (m *Manager) CheckGrantPeriods(ctx context.Context) ([]string, error)

CheckGrantPeriods reviews all projects and auto-freezes any where the grant period has ended and AutoFreeze=true. Intended to be called by a daemon ticker (daily). Returns the list of auto-frozen project IDs.

func (*Manager) CheckQuota added in v0.12.0

func (m *Manager) CheckQuota(projectID, userID, instanceType string, instanceCount int) error

CheckQuota verifies whether a launch by the given user satisfies the project's role quotas. instanceCount is the number of instances already owned by this user. Returns a non-nil error if the launch would violate a quota.

func (*Manager) ClearDefaultAllocation added in v0.5.10

func (m *Manager) ClearDefaultAllocation(ctx context.Context, projectID string) error

ClearDefaultAllocation clears the default funding allocation for a project (v0.5.10+)

func (*Manager) Close

func (m *Manager) Close() error

Close cleanly shuts down the project manager

func (*Manager) CreateProject

func (m *Manager) CreateProject(ctx context.Context, req *CreateProjectRequest) (*types.Project, error)

CreateProject creates a new research project

func (*Manager) CurrentMonthAllocation added in v0.12.0

func (m *Manager) CurrentMonthAllocation(projectID string) (float64, error)

CurrentMonthAllocation returns the per-month allocation for a multi-month budget (#144). Returns TotalBudget if AllocationMonths <= 1.

func (*Manager) DeleteGrantPeriod added in v0.12.0

func (m *Manager) DeleteGrantPeriod(ctx context.Context, projectID string) error

DeleteGrantPeriod removes the grant period from a project.

func (*Manager) DeleteOnboardingTemplate added in v0.12.0

func (m *Manager) DeleteOnboardingTemplate(ctx context.Context, projectID, nameOrID string) error

DeleteOnboardingTemplate removes an onboarding template by name or ID.

func (*Manager) DeleteProject

func (m *Manager) DeleteProject(ctx context.Context, projectID string) error

DeleteProject removes a project and all associated data

func (*Manager) DisableProjectBudget

func (m *Manager) DisableProjectBudget(ctx context.Context, projectID string) error

DisableProjectBudget disables budget tracking for a project

func (*Manager) GetGrantPeriod added in v0.12.0

func (m *Manager) GetGrantPeriod(projectID string) (*types.GrantPeriod, error)

GetGrantPeriod returns the current grant period for a project.

func (*Manager) GetProject

func (m *Manager) GetProject(ctx context.Context, projectID string) (*types.Project, error)

GetProject retrieves a project by ID

func (*Manager) GetProjectByName

func (m *Manager) GetProjectByName(ctx context.Context, name string) (*types.Project, error)

GetProjectByName retrieves a project by name

func (*Manager) GetProjectCostBreakdown

func (m *Manager) GetProjectCostBreakdown(ctx context.Context, projectID string, startDate, endDate time.Time) (*types.ProjectCostBreakdown, error)

GetProjectCostBreakdown retrieves detailed cost analysis for a project

func (*Manager) GetProjectForecast added in v0.6.0

func (m *Manager) GetProjectForecast(ctx context.Context, projectID string, req *ProjectForecastRequest) (*ProjectForecastResponse, error)

GetProjectForecast generates cost forecast data for a project using linear regression.

func (*Manager) GetProjectResourceUsage

func (m *Manager) GetProjectResourceUsage(ctx context.Context, projectID string, period time.Duration) (*types.ProjectResourceUsage, error)

GetProjectResourceUsage retrieves resource utilization metrics for a project

func (*Manager) GetRoleQuotas added in v0.12.0

func (m *Manager) GetRoleQuotas(projectID string) ([]types.RoleQuota, error)

GetRoleQuotas returns the role quotas for a project's budget.

func (*Manager) IsLaunchPrevented

func (m *Manager) IsLaunchPrevented(ctx context.Context, projectID string) (bool, error)

IsLaunchPrevented checks if launches are prevented for a project

func (*Manager) ListProjects

func (m *Manager) ListProjects(ctx context.Context, filter *ProjectFilter) ([]*types.Project, error)

ListProjects retrieves projects with optional filtering

func (*Manager) PreventLaunches

func (m *Manager) PreventLaunches(ctx context.Context, projectID string) error

PreventLaunches prevents new instance launches for a project

func (*Manager) PruneExpiredMembers added in v0.12.0

func (m *Manager) PruneExpiredMembers(ctx context.Context) ([]string, error)

PruneExpiredMembers removes members whose ExpiresAt has passed. Intended to be called by a daemon background ticker (hourly). Returns the list of removed member UserIDs.

func (*Manager) RemoveProjectMember

func (m *Manager) RemoveProjectMember(ctx context.Context, projectID, userID string) error

RemoveProjectMember removes a member from a project

func (*Manager) SetAlerter added in v0.12.0

func (m *Manager) SetAlerter(d alerting.AlertDispatcher)

SetAlerter passes an AlertDispatcher through to the underlying BudgetTracker. This allows operators to configure notification backends (Slack, webhook, etc.) at daemon startup without re-creating the budget tracker.

func (*Manager) SetDefaultAllocation added in v0.5.10

func (m *Manager) SetDefaultAllocation(ctx context.Context, projectID string, allocationID string) error

SetDefaultAllocation sets the default funding allocation for a project (v0.5.10+)

func (*Manager) SetGrantPeriod added in v0.12.0

func (m *Manager) SetGrantPeriod(ctx context.Context, projectID string, gp *types.GrantPeriod) error

SetGrantPeriod sets the grant period for a project budget.

func (*Manager) SetOnboardingTemplate added in v0.12.0

func (m *Manager) SetOnboardingTemplate(ctx context.Context, projectID string, tmpl types.OnboardingTemplate) error

SetOnboardingTemplate upserts an onboarding template for a project.

func (*Manager) SetProjectBudget

func (m *Manager) SetProjectBudget(ctx context.Context, projectID string, budget *types.ProjectBudget) error

SetProjectBudget sets or enables budget tracking for a project

func (*Manager) SetRoleQuota added in v0.12.0

func (m *Manager) SetRoleQuota(ctx context.Context, projectID string, quota types.RoleQuota) error

SetRoleQuota upserts a role quota for a project.

func (*Manager) ShareBudget added in v0.12.0

func (m *Manager) ShareBudget(ctx context.Context, req *types.BudgetShareRequest, approvedBy string) (*types.BudgetShareRecord, error)

ShareBudget executes a budget share between projects or members. The amount is subtracted from the source project's TotalBudget and added to the destination, with a BudgetShareRecord created for audit purposes.

func (*Manager) TransferProject added in v0.6.0

func (m *Manager) TransferProject(ctx context.Context, projectID string, req *TransferProjectRequest) (*types.Project, error)

TransferProject transfers project ownership to a new owner

func (*Manager) UpdateProject

func (m *Manager) UpdateProject(ctx context.Context, projectID string, req *UpdateProjectRequest) (*types.Project, error)

UpdateProject updates an existing project

func (*Manager) UpdateProjectBudget

func (m *Manager) UpdateProjectBudget(ctx context.Context, projectID string, budget *types.ProjectBudget) error

UpdateProjectBudget updates an existing project budget

func (*Manager) UpdateProjectMember

func (m *Manager) UpdateProjectMember(ctx context.Context, projectID, userID string, role types.ProjectRole) error

UpdateProjectMember updates a member's role in a project

type MonthlyReport added in v0.12.0

type MonthlyReport struct {
	ProjectID   string              `json:"project_id"`
	Month       string              `json:"month"` // "2026-02"
	TotalSpend  float64             `json:"total_spend"`
	ByInstance  []InstanceSpendLine `json:"by_instance"`
	ByStorage   []StorageSpendLine  `json:"by_storage"`
	BudgetLimit float64             `json:"budget_limit"`
	Utilization float64             `json:"utilization"` // 0.0-1.0
	GeneratedAt time.Time           `json:"generated_at"`
}

MonthlyReport contains a full monthly budget report for a project

func GenerateMonthlyReport added in v0.12.0

func GenerateMonthlyReport(projectID, month string, history []CostDataPoint, budget *types.ProjectBudget) (*MonthlyReport, error)

GenerateMonthlyReport builds a MonthlyReport from cost history for the given month. month format: "2026-02" (YYYY-MM)

func (*MonthlyReport) RenderCSV added in v0.12.0

func (r *MonthlyReport) RenderCSV() string

RenderCSV returns a CSV-formatted report (two sections: instances, storage)

func (*MonthlyReport) RenderJSON added in v0.12.0

func (r *MonthlyReport) RenderJSON() ([]byte, error)

RenderJSON returns the report as indented JSON bytes

func (*MonthlyReport) RenderText added in v0.12.0

func (r *MonthlyReport) RenderText() string

RenderText returns a human-readable text report

type PaceStatus added in v0.11.0

type PaceStatus string

PaceStatus describes whether spending is on track relative to the budget period.

const (
	// PaceStatusOnPace means within ±10% of expected rate.
	PaceStatusOnPace PaceStatus = "on_pace"
	// PaceStatusAhead means spending faster than expected.
	PaceStatusAhead PaceStatus = "ahead"
	// PaceStatusBehind means spending slower than expected.
	PaceStatusBehind PaceStatus = "behind"
	// PaceStatusOverBudget means the period allocation is already exceeded.
	PaceStatusOverBudget PaceStatus = "over_budget"
)

type PeriodWindow added in v0.11.0

type PeriodWindow struct {
	Start         time.Time          `json:"start"`
	End           time.Time          `json:"end"`
	TotalDays     float64            `json:"total_days"`
	ElapsedDays   float64            `json:"elapsed_days"`
	RemainingDays float64            `json:"remaining_days"`
	PeriodType    types.BudgetPeriod `json:"period_type"`
}

PeriodWindow represents a normalized budget period window.

type ProjectBudgetData

type ProjectBudgetData struct {
	ProjectID    string               `json:"project_id"`
	Budget       *types.ProjectBudget `json:"budget"`
	CostHistory  []CostDataPoint      `json:"cost_history"`
	AlertHistory []AlertEvent         `json:"alert_history"`
	LastUpdated  time.Time            `json:"last_updated"`
}

ProjectBudgetData stores budget tracking data for a project

type ProjectCostSummary added in v0.5.10

type ProjectCostSummary struct {
	// ProjectID is the project identifier
	ProjectID string `json:"project_id"`

	// ProjectName is the project name
	ProjectName string `json:"project_name"`

	// FundingSources lists all funding allocations for this project
	FundingSources []AllocationSummary `json:"funding_sources"`

	// TotalAllocated is the total allocated to this project across all sources
	TotalAllocated float64 `json:"total_allocated"`

	// TotalSpent is the total spent by this project
	TotalSpent float64 `json:"total_spent"`

	// TotalRemaining is the remaining budget for this project
	TotalRemaining float64 `json:"total_remaining"`

	// Utilization is the percentage of allocated budget spent (0.0-1.0)
	Utilization float64 `json:"utilization"`
}

ProjectCostSummary provides project-level cost information (v0.5.10+ Issue #100)

type ProjectFilter

type ProjectFilter struct {
	// Owner filters by project owner
	Owner string `json:"owner,omitempty"`

	// Status filters by project status
	Status *types.ProjectStatus `json:"status,omitempty"`

	// Tags filters by project tags (all specified tags must match)
	Tags map[string]string `json:"tags,omitempty"`

	// CreatedAfter filters projects created after this date
	CreatedAfter *time.Time `json:"created_after,omitempty"`

	// CreatedBefore filters projects created before this date
	CreatedBefore *time.Time `json:"created_before,omitempty"`

	// HasBudget filters projects with/without budgets
	HasBudget *bool `json:"has_budget,omitempty"`
}

ProjectFilter defines filtering options for listing projects

func (*ProjectFilter) Matches

func (f *ProjectFilter) Matches(project *types.Project) bool

Matches checks if a project matches the filter criteria

type ProjectForecastRequest added in v0.6.0

type ProjectForecastRequest struct {
	// Months is the number of months to forecast (default: 6)
	Months int `json:"months,omitempty"`

	// IncludeHistorical includes historical spending data in response
	IncludeHistorical bool `json:"include_historical,omitempty"`
}

ProjectForecastRequest represents a request for cost forecast data

type ProjectForecastResponse added in v0.6.0

type ProjectForecastResponse struct {
	// ProjectID is the project identifier
	ProjectID string `json:"project_id"`

	// GeneratedAt is when this forecast was generated
	GeneratedAt time.Time `json:"generated_at"`

	// CurrentMonthlyRate is the current monthly spending rate
	CurrentMonthlyRate float64 `json:"current_monthly_rate"`

	// ForecastData contains month-by-month projections
	ForecastData []ForecastDataPoint `json:"forecast_data"`

	// HistoricalData contains past spending (if requested)
	HistoricalData []ForecastDataPoint `json:"historical_data,omitempty"`

	// ProjectedExhaustion estimates when budget will be exhausted (if applicable)
	ProjectedExhaustion *time.Time `json:"projected_exhaustion,omitempty"`

	// Confidence indicates forecast confidence level (0.0-1.0)
	Confidence float64 `json:"confidence"`
}

ProjectForecastResponse provides cost forecast information

type ProjectListResponse

type ProjectListResponse struct {
	// Projects are the matching projects
	Projects []ProjectSummary `json:"projects"`

	// TotalCount is the total number of projects (before pagination)
	TotalCount int `json:"total_count"`

	// FilteredCount is the number of projects matching the filter
	FilteredCount int `json:"filtered_count"`
}

ProjectListResponse represents the response for listing projects

type ProjectSummary

type ProjectSummary struct {
	// ID is the project identifier
	ID string `json:"id"`

	// Name is the project name
	Name string `json:"name"`

	// Owner is the project owner
	Owner string `json:"owner"`

	// Status is the project status
	Status types.ProjectStatus `json:"status"`

	// MemberCount is the number of project members
	MemberCount int `json:"member_count"`

	// ActiveInstances is the number of currently active instances
	ActiveInstances int `json:"active_instances"`

	// TotalCost is the total project cost to date
	TotalCost float64 `json:"total_cost"`

	// BudgetStatus provides budget information if budget is enabled
	BudgetStatus *BudgetStatusSummary `json:"budget_status,omitempty"`

	// CreatedAt is when the project was created
	CreatedAt time.Time `json:"created_at"`

	// LastActivity is when the project had its last activity
	LastActivity time.Time `json:"last_activity"`
}

ProjectSummary provides a condensed view of project information

type ReallocateFundsRequest added in v0.5.10

type ReallocateFundsRequest struct {
	// SourceAllocationID is where funds are moved from
	SourceAllocationID string `json:"source_allocation_id"`

	// DestinationAllocationID is where funds are moved to
	DestinationAllocationID string `json:"destination_allocation_id"`

	// Amount is how much to reallocate (USD)
	Amount float64 `json:"amount"`

	// Reason explains why the reallocation is being made (required for audit)
	Reason string `json:"reason"`

	// PerformedBy is the user making the reallocation
	PerformedBy string `json:"performed_by"`
}

ReallocateFundsRequest represents a request to reallocate funds between allocations (v0.5.10+ Issue #99)

func (*ReallocateFundsRequest) Validate added in v0.5.10

func (r *ReallocateFundsRequest) Validate() error

Validate validates the reallocate funds request

type ReallocationRecord added in v0.5.10

type ReallocationRecord struct {
	// ID is the unique reallocation identifier
	ID string `json:"id"`

	// SourceAllocationID is where funds were moved from
	SourceAllocationID string `json:"source_allocation_id"`

	// DestinationAllocationID is where funds were moved to
	DestinationAllocationID string `json:"destination_allocation_id"`

	// SourceBudgetID is the source budget (for cross-budget tracking)
	SourceBudgetID string `json:"source_budget_id"`

	// DestinationBudgetID is the destination budget (for cross-budget tracking)
	DestinationBudgetID string `json:"destination_budget_id"`

	// Amount is how much was reallocated (USD)
	Amount float64 `json:"amount"`

	// Reason explains why the reallocation was made
	Reason string `json:"reason"`

	// PerformedBy is the user who made the reallocation
	PerformedBy string `json:"performed_by"`

	// Timestamp is when the reallocation occurred
	Timestamp time.Time `json:"timestamp"`
}

ReallocationRecord tracks a funds reallocation for audit purposes (v0.5.10+ Issue #99)

type S3CostDetail added in v0.11.0

type S3CostDetail struct {
	BucketName       string             `json:"bucket_name"`
	Region           string             `json:"region"`
	StorageCost      float64            `json:"storage_cost"`
	RequestCost      float64            `json:"request_cost"`
	EgressCost       float64            `json:"egress_cost"`
	ReplicationCost  float64            `json:"replication_cost"`
	TotalMonthlyCost float64            `json:"total_monthly_cost"`
	StorageBreakdown map[string]float64 `json:"storage_breakdown"` // class -> $
}

S3CostDetail is the output struct for a single S3 bucket cost breakdown.

type S3CostSpec added in v0.11.0

type S3CostSpec struct {
	BucketName            string
	Region                string
	StorageClassBreakdown map[string]int64 // storage_class -> bytes
	RequestCounts         map[string]int64 // "GET","PUT","LIST","DELETE" -> count
	DataTransferGB        float64          // data transferred OUT (egress)
	ReplicationGB         float64          // cross-region replication GB
}

S3CostSpec contains S3 bucket usage data for cost calculation.

type ShortfallPrediction added in v0.11.0

type ShortfallPrediction struct {
	ProjectID             string             `json:"project_id"`
	GeneratedAt           time.Time          `json:"generated_at"`
	CurrentDailyRate      float64            `json:"current_daily_rate"`
	TrendSlope            float64            `json:"trend_slope"` // $/day change per day (acceleration)
	PredictedExhaustionAt *time.Time         `json:"predicted_exhaustion_at,omitempty"`
	DaysUntilExhaustion   *int               `json:"days_until_exhaustion,omitempty"`
	WillExceedBudget      bool               `json:"will_exceed_budget"`
	ProbabilityExceed     float64            `json:"probability_exceed"` // 0.0–1.0
	ConfidenceLevel       string             `json:"confidence_level"`   // low / medium / high
	MonthlyForecasts      []ForecastMonth    `json:"monthly_forecasts"`
	GrantRenewalAlert     *GrantRenewalAlert `json:"grant_renewal_alert,omitempty"`
}

ShortfallPrediction contains all forward-looking budget analysis.

type SpendingResult added in v0.5.10

type SpendingResult struct {
	AllocationID        string
	AllocationExhausted bool
	BackupActivated     bool
	BackupAllocationID  string
	WarningMessage      string
}

SpendingResult contains information about spending and potential backup activation

type StorageSpendLine added in v0.12.0

type StorageSpendLine struct {
	VolumeName string  `json:"volume_name"`
	VolumeType string  `json:"volume_type"`
	SizeGB     float64 `json:"size_gb"`
	Cost       float64 `json:"cost"`
}

StorageSpendLine is a single storage row in a monthly report

type SurplusCalculator added in v0.11.0

type SurplusCalculator struct{}

SurplusCalculator handles budget banking and carry-over across periods.

func (*SurplusCalculator) BankedSurplus added in v0.11.0

func (s *SurplusCalculator) BankedSurplus(
	history []CostDataPoint,
	period types.BudgetPeriod,
	startDate time.Time,
	periodAllocation float64,
) float64

BankedSurplus returns the total accumulated surplus across all completed periods prior to the current one. Only meaningful for monthly/weekly/daily periods.

func (*SurplusCalculator) ComputeSurplus added in v0.11.0

func (s *SurplusCalculator) ComputeSurplus(
	history []CostDataPoint,
	period types.BudgetPeriod,
	startDate time.Time,
	totalBudget float64,
	periodAllocation float64,
	surplusCapPercent float64,
) *SurplusInfo

ComputeSurplus builds a fully populated SurplusInfo for a project budget.

func (*SurplusCalculator) ComputeSurplusWithRollover added in v0.12.0

func (s *SurplusCalculator) ComputeSurplusWithRollover(
	history []CostDataPoint,
	budget *types.ProjectBudget,
	periodAllocation float64,
) *SurplusInfo

ComputeSurplusWithRollover builds a SurplusInfo respecting the v0.12.0 rollover configuration fields on ProjectBudget (#143).

When RolloverEnabled=false the behaviour is identical to ComputeSurplus with surplusCapPercent=0. When RolloverEnabled=true the cap is derived from RolloverCap (absolute dollar amount) unless it is 0, in which case there is no cap (surplusCapPercent=1.0 acts as 100%).

func (*SurplusCalculator) EffectiveBalance added in v0.11.0

func (s *SurplusCalculator) EffectiveBalance(periodAllocation, bankedSurplus, totalBudget, surplusCapPercent float64) float64

EffectiveBalance returns the allocation for the current period plus banked surplus, subject to the surplus cap.

surplusCapPercent=0 means banking is disabled; surplusCapPercent=0.20 means at most 20% of totalBudget can carry over.

func (*SurplusCalculator) PeriodSurplus added in v0.11.0

func (s *SurplusCalculator) PeriodSurplus(history []CostDataPoint, window PeriodWindow, allocation float64) float64

PeriodSurplus returns the unspent amount in the given window relative to its allocation. A negative value means the window was over-budget.

type SurplusInfo added in v0.11.0

type SurplusInfo struct {
	// CurrentPeriodSurplus is unspent amount in the current period (negative = over budget).
	CurrentPeriodSurplus float64 `json:"current_period_surplus"`
	// BankedSurplus is accumulated carry-over from prior completed periods.
	BankedSurplus float64 `json:"banked_surplus"`
	// EffectiveBalance is the current period allocation plus banked surplus (capped).
	EffectiveBalance float64 `json:"effective_balance"`
	// SurplusCapPercent is the maximum carry-over as a fraction of the total budget.
	SurplusCapPercent float64 `json:"surplus_cap_percent"`
	// SurplusCapped is true when the cap was applied.
	SurplusCapped bool `json:"surplus_capped"`
}

SurplusInfo contains banking and carry-over information for a project budget.

type TransferProjectRequest added in v0.6.0

type TransferProjectRequest struct {
	// NewOwnerID is the user ID of the new project owner
	NewOwnerID string `json:"new_owner_id"`

	// TransferredBy is the user making the transfer (must be current owner)
	TransferredBy string `json:"transferred_by"`

	// Reason provides context for the transfer (optional)
	Reason string `json:"reason,omitempty"`
}

TransferProjectRequest represents a request to transfer project ownership

func (*TransferProjectRequest) Validate added in v0.6.0

func (r *TransferProjectRequest) Validate() error

Validate validates the transfer project request

type UpdateAllocationRequest added in v0.5.10

type UpdateAllocationRequest struct {
	// AllocatedAmount is the new allocated amount (optional)
	AllocatedAmount *float64 `json:"allocated_amount,omitempty"`

	// AlertThreshold is the new alert threshold (optional)
	AlertThreshold *float64 `json:"alert_threshold,omitempty"`

	// BackupAllocationID is the new backup allocation (optional)
	BackupAllocationID *string `json:"backup_allocation_id,omitempty"`

	// Notes are the new notes (optional)
	Notes *string `json:"notes,omitempty"`
}

UpdateAllocationRequest represents a request to update an allocation

type UpdateBudgetRequest added in v0.5.10

type UpdateBudgetRequest struct {
	// Name is the new budget name (optional)
	Name *string `json:"name,omitempty"`

	// Description is the new budget description (optional)
	Description *string `json:"description,omitempty"`

	// TotalAmount is the new total amount (optional)
	TotalAmount *float64 `json:"total_amount,omitempty"`

	// AlertThreshold is the new alert threshold (optional)
	AlertThreshold *float64 `json:"alert_threshold,omitempty"`

	// EndDate is the new end date (optional)
	EndDate *time.Time `json:"end_date,omitempty"`

	// Tags are the new budget tags (optional)
	Tags map[string]string `json:"tags,omitempty"`
}

UpdateBudgetRequest represents a request to update a budget

type UpdateMemberRequest

type UpdateMemberRequest struct {
	// Role is the new role for the member
	Role types.ProjectRole `json:"role"`
}

UpdateMemberRequest represents a request to update a project member

func (*UpdateMemberRequest) Validate

func (r *UpdateMemberRequest) Validate() error

Validate validates the update member request

type UpdateProjectRequest

type UpdateProjectRequest struct {
	// Name is the new project name (optional)
	Name *string `json:"name,omitempty"`

	// Description is the new project description (optional)
	Description *string `json:"description,omitempty"`

	// Tags are the new project tags (optional)
	Tags map[string]string `json:"tags,omitempty"`

	// Status is the new project status (optional)
	Status *types.ProjectStatus `json:"status,omitempty"`
}

UpdateProjectRequest represents a request to update a project

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL