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 ¶
- Variables
- func ApplyAdjustments(baseCost float64, adj *CostAdjustments) float64
- func FormatAdjustmentSummary(adj *CostAdjustments) string
- func SumCreditBalance(credits []AWSCredit) float64
- func SumMonthlySavings(discounts []AWSDiscount, monthlySpend float64) (totalSavings float64, effectiveRate float64)
- type AWSCredit
- type AWSDiscount
- type ActionExecutor
- type AddMemberRequest
- type AlertEvent
- type AllocationSummary
- type ApprovalManager
- func (am *ApprovalManager) Approve(id, reviewerID, note string) (*ApprovalRequest, error)
- func (am *ApprovalManager) Deny(id, reviewerID, note string) (*ApprovalRequest, error)
- func (am *ApprovalManager) Get(id string) (*ApprovalRequest, error)
- func (am *ApprovalManager) List(projectID string, status ApprovalStatus) ([]*ApprovalRequest, error)
- func (am *ApprovalManager) PruneExpired() (int, error)
- func (am *ApprovalManager) Submit(projectID, requestedBy string, typ ApprovalType, ...) (*ApprovalRequest, error)
- type ApprovalRequest
- type ApprovalStatus
- type ApprovalType
- type BudgetManager
- func (bm *BudgetManager) ActivateBackupFunding(ctx context.Context, projectID string, primaryAllocationID string, ...) error
- func (bm *BudgetManager) CheckAllocationStatus(ctx context.Context, allocationID string) (exhausted bool, remaining float64, err error)
- func (bm *BudgetManager) Close() error
- func (bm *BudgetManager) CreateAllocation(ctx context.Context, req *CreateAllocationRequest) (*types.ProjectBudgetAllocation, error)
- func (bm *BudgetManager) CreateBudget(ctx context.Context, req *CreateBudgetRequest) (*types.Budget, error)
- func (bm *BudgetManager) DeleteAllocation(ctx context.Context, allocationID string) error
- func (bm *BudgetManager) DeleteBudget(ctx context.Context, budgetID string) error
- func (bm *BudgetManager) GenerateBudgetRollupReport(ctx context.Context) (*BudgetRollupReport, error)
- func (bm *BudgetManager) GetAllocation(ctx context.Context, allocationID string) (*types.ProjectBudgetAllocation, error)
- func (bm *BudgetManager) GetBudget(ctx context.Context, budgetID string) (*types.Budget, error)
- func (bm *BudgetManager) GetBudgetAllocations(ctx context.Context, budgetID string) ([]*types.ProjectBudgetAllocation, error)
- func (bm *BudgetManager) GetBudgetByName(ctx context.Context, name string) (*types.Budget, error)
- func (bm *BudgetManager) GetBudgetReallocationHistory(ctx context.Context, budgetID string) ([]*ReallocationRecord, error)
- func (bm *BudgetManager) GetBudgetSummary(ctx context.Context, budgetID string) (*types.BudgetSummary, error)
- func (bm *BudgetManager) GetBudgetSummaryReport(ctx context.Context, budgetID string) (*BudgetSummaryReport, error)
- func (bm *BudgetManager) GetProjectAllocations(ctx context.Context, projectID string) ([]*types.ProjectBudgetAllocation, error)
- func (bm *BudgetManager) GetProjectCostRollup(ctx context.Context, projectIDs []string) ([]ProjectCostSummary, error)
- func (bm *BudgetManager) GetProjectFundingSummary(ctx context.Context, projectID string) (*types.ProjectFundingSummary, error)
- func (bm *BudgetManager) GetReallocationHistory(ctx context.Context, allocationID string) ([]*ReallocationRecord, error)
- func (bm *BudgetManager) ListBudgets(ctx context.Context) ([]*types.Budget, error)
- func (bm *BudgetManager) ReallocateFunds(ctx context.Context, req *ReallocateFundsRequest) (*ReallocationRecord, error)
- func (bm *BudgetManager) RecordSpending(ctx context.Context, allocationID string, amount float64) (*SpendingResult, error)
- func (bm *BudgetManager) SetProjectManager(m *Manager)
- func (bm *BudgetManager) UpdateAllocation(ctx context.Context, allocationID string, req *UpdateAllocationRequest) (*types.ProjectBudgetAllocation, error)
- func (bm *BudgetManager) UpdateBudget(ctx context.Context, budgetID string, req *UpdateBudgetRequest) (*types.Budget, error)
- type BudgetPredictor
- type BudgetRollupReport
- type BudgetStatus
- type BudgetStatusSummary
- type BudgetSummaryReport
- type BudgetTracker
- func (bt *BudgetTracker) CheckBudgetStatus(projectID string) (*BudgetStatus, error)
- func (bt *BudgetTracker) Close() error
- func (bt *BudgetTracker) GetAllProjectIDs() []string
- func (bt *BudgetTracker) GetBudgetStatus(projectID string) (map[string]interface{}, error)
- func (bt *BudgetTracker) GetCostBreakdown(projectID string, startDate, endDate time.Time) (*types.ProjectCostBreakdown, error)
- func (bt *BudgetTracker) GetCostHistory(projectID string) ([]CostDataPoint, error)
- func (bt *BudgetTracker) GetCostTrends(projectID string, period string) (map[string]interface{}, error)
- func (bt *BudgetTracker) GetCurrentMonthlyRate(projectID string) float64
- func (bt *BudgetTracker) GetProjectCostHistory(projectID string, days int) ([]float64, error)
- func (bt *BudgetTracker) GetResourceUsage(projectID string, period time.Duration) (*types.ProjectResourceUsage, error)
- func (bt *BudgetTracker) InitializeProject(projectID string, budget *types.ProjectBudget) error
- func (bt *BudgetTracker) RemoveProject(projectID string) error
- func (bt *BudgetTracker) SetActionExecutor(executor ActionExecutor)
- func (bt *BudgetTracker) SetAlerter(d alerting.AlertDispatcher)
- func (bt *BudgetTracker) UpdateProjectCosts(projectID string, instances []types.Instance, ...) error
- func (bt *BudgetTracker) UpdateProjectSpending(projectID string, instanceCosts []types.InstanceCost, ...) error
- type BurnRateCalculator
- func (b *BurnRateCalculator) BurnRateVsAllocation(history []CostDataPoint, window PeriodWindow, totalAllocation float64) (float64, float64, float64)
- func (b *BurnRateCalculator) ComputeBurnRate(history []CostDataPoint, period types.BudgetPeriod, startDate time.Time, ...) *BurnRateInfo
- func (b *BurnRateCalculator) CurrentPeriodWindow(period types.BudgetPeriod, startDate time.Time) PeriodWindow
- func (b *BurnRateCalculator) DailyBurnRate(history []CostDataPoint, windowDays int) float64
- func (b *BurnRateCalculator) PeriodSpend(history []CostDataPoint, window PeriodWindow) float64
- func (b *BurnRateCalculator) WeeklyBurnRate(history []CostDataPoint) float64
- type BurnRateInfo
- type CostAdjustments
- type CostCalculator
- func (c *CostCalculator) ApplyDiscount(baseCost float64, config *types.DiscountConfig, serviceType string) float64
- func (c *CostCalculator) CalculateEBSCost(spec EBSVolumeSpec) EBSCostDetail
- func (c *CostCalculator) CalculateEFSCost(spec EFSVolumeSpec) EFSCostDetail
- func (c *CostCalculator) CalculateInstanceCosts(instances []types.Instance) ([]types.InstanceCost, float64)
- func (c *CostCalculator) CalculateS3Cost(spec S3CostSpec) S3CostDetail
- func (c *CostCalculator) CalculateStorageCosts(storageVolumes []types.StorageVolume) ([]types.StorageCost, float64)
- func (c *CostCalculator) EstimateHibernationSavings(instanceType string, hibernatedHours float64) float64
- func (c *CostCalculator) EstimateMonthlyCost(instanceType string, storageGB int) float64
- func (c *CostCalculator) GetInstanceHourlyRate(instanceType string) float64
- func (c *CostCalculator) GetStorageMonthlyRate(storageType string) float64
- type CostDataPoint
- type CreateAllocationRequest
- type CreateBudgetRequest
- type CreateProjectBudgetRequest
- type CreateProjectRequest
- type CushionConfig
- type CushionEvaluator
- type CushionMode
- type CushionStatus
- type DiscoveryResult
- type EBSCostDetail
- type EBSVolumeSpec
- type EFSCostDetail
- type EFSVolumeSpec
- type ForecastDataPoint
- type ForecastMonth
- type GDEWStatus
- type GDEWTracker
- type GrantRenewalAlert
- type InstanceSpendLine
- type Manager
- func (m *Manager) AddProjectMember(ctx context.Context, projectID string, member *types.ProjectMember) error
- func (m *Manager) AllowLaunches(ctx context.Context, projectID string) error
- func (m *Manager) CheckBudgetStatus(ctx context.Context, projectID string) (*BudgetStatus, error)
- func (m *Manager) CheckGrantPeriods(ctx context.Context) ([]string, error)
- func (m *Manager) CheckQuota(projectID, userID, instanceType string, instanceCount int) error
- func (m *Manager) ClearDefaultAllocation(ctx context.Context, projectID string) error
- func (m *Manager) Close() error
- func (m *Manager) CreateProject(ctx context.Context, req *CreateProjectRequest) (*types.Project, error)
- func (m *Manager) CurrentMonthAllocation(projectID string) (float64, error)
- func (m *Manager) DeleteGrantPeriod(ctx context.Context, projectID string) error
- func (m *Manager) DeleteOnboardingTemplate(ctx context.Context, projectID, nameOrID string) error
- func (m *Manager) DeleteProject(ctx context.Context, projectID string) error
- func (m *Manager) DisableProjectBudget(ctx context.Context, projectID string) error
- func (m *Manager) GetGrantPeriod(projectID string) (*types.GrantPeriod, error)
- func (m *Manager) GetProject(ctx context.Context, projectID string) (*types.Project, error)
- func (m *Manager) GetProjectByName(ctx context.Context, name string) (*types.Project, error)
- func (m *Manager) GetProjectCostBreakdown(ctx context.Context, projectID string, startDate, endDate time.Time) (*types.ProjectCostBreakdown, error)
- func (m *Manager) GetProjectForecast(ctx context.Context, projectID string, req *ProjectForecastRequest) (*ProjectForecastResponse, error)
- func (m *Manager) GetProjectResourceUsage(ctx context.Context, projectID string, period time.Duration) (*types.ProjectResourceUsage, error)
- func (m *Manager) GetRoleQuotas(projectID string) ([]types.RoleQuota, error)
- func (m *Manager) IsLaunchPrevented(ctx context.Context, projectID string) (bool, error)
- func (m *Manager) ListProjects(ctx context.Context, filter *ProjectFilter) ([]*types.Project, error)
- func (m *Manager) PreventLaunches(ctx context.Context, projectID string) error
- func (m *Manager) PruneExpiredMembers(ctx context.Context) ([]string, error)
- func (m *Manager) RemoveProjectMember(ctx context.Context, projectID, userID string) error
- func (m *Manager) SetActiveInstancesFunc(fn func(projectID string) ([]string, error))
- func (m *Manager) SetAlerter(d alerting.AlertDispatcher)
- func (m *Manager) SetDefaultAllocation(ctx context.Context, projectID string, allocationID string) error
- func (m *Manager) SetGrantPeriod(ctx context.Context, projectID string, gp *types.GrantPeriod) error
- func (m *Manager) SetOnboardingTemplate(ctx context.Context, projectID string, tmpl types.OnboardingTemplate) error
- func (m *Manager) SetProjectBudget(ctx context.Context, projectID string, budget *types.ProjectBudget) error
- func (m *Manager) SetRoleQuota(ctx context.Context, projectID string, quota types.RoleQuota) error
- func (m *Manager) ShareBudget(ctx context.Context, req *types.BudgetShareRequest, approvedBy string) (*types.BudgetShareRecord, error)
- func (m *Manager) TransferProject(ctx context.Context, projectID string, req *TransferProjectRequest) (*types.Project, error)
- func (m *Manager) UpdateProject(ctx context.Context, projectID string, req *UpdateProjectRequest) (*types.Project, error)
- func (m *Manager) UpdateProjectBudget(ctx context.Context, projectID string, budget *types.ProjectBudget) error
- func (m *Manager) UpdateProjectMember(ctx context.Context, projectID, userID string, role types.ProjectRole) error
- type MonthlyReport
- type PaceStatus
- type PeriodWindow
- type ProjectBudgetData
- type ProjectCostSummary
- type ProjectFilter
- type ProjectForecastRequest
- type ProjectForecastResponse
- type ProjectListResponse
- type ProjectSummary
- type ReallocateFundsRequest
- type ReallocationRecord
- type S3CostDetail
- type S3CostSpec
- type ShortfallPrediction
- type SpendingResult
- type StorageSpendLine
- type SurplusCalculator
- func (s *SurplusCalculator) BankedSurplus(history []CostDataPoint, period types.BudgetPeriod, startDate time.Time, ...) float64
- func (s *SurplusCalculator) ComputeSurplus(history []CostDataPoint, period types.BudgetPeriod, startDate time.Time, ...) *SurplusInfo
- func (s *SurplusCalculator) ComputeSurplusWithRollover(history []CostDataPoint, budget *types.ProjectBudget, periodAllocation float64) *SurplusInfo
- func (s *SurplusCalculator) EffectiveBalance(periodAllocation, bankedSurplus, totalBudget, surplusCapPercent float64) float64
- func (s *SurplusCalculator) PeriodSurplus(history []CostDataPoint, window PeriodWindow, allocation float64) float64
- type SurplusInfo
- type TransferProjectRequest
- type UpdateAllocationRequest
- type UpdateBudgetRequest
- type UpdateMemberRequest
- type UpdateProjectRequest
Constants ¶
This section is empty.
Variables ¶
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
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
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, persisting through the seam (design §5).
Persistence is no longer inlined file I/O: it goes through a seam.Store[ApprovalRequest], so the SAME manager logic backs the desktop (filestore) and the shared cloud (dynamostore). A record written by prp (web) is the same record Prism (desktop) reads — that is the shared-state guarantee (design §4), not a sync protocol.
On the desktop the scope is the zero Scope (single-tenant); the cloud deployment sets a per-Principal scope via NewApprovalManagerForScope, and nothing else here changes — that is the point of the seam.
func NewApprovalManager ¶ added in v0.12.0
func NewApprovalManager() (*ApprovalManager, error)
NewApprovalManager creates an approval manager persisting to ~/.prism (via the file-backed seam store). Signature unchanged, so existing callers (the daemon) need no edit. Any legacy ~/.prism/approvals.json is migrated into the seam on first construction.
func NewApprovalManagerForScope ¶ added in v0.36.0
func NewApprovalManagerForScope(store seam.Store[ApprovalRequest], scope seam.Scope) *ApprovalManager
NewApprovalManagerForScope builds a manager over an injected store scoped to a Principal — the cloud/multi-tenant entry point. Records partition by scope (tenant/pi/grant); the method logic is unchanged from the desktop path.
func NewApprovalManagerWithStore ¶ added in v0.36.0
func NewApprovalManagerWithStore(store seam.Store[ApprovalRequest]) *ApprovalManager
NewApprovalManagerWithStore builds a manager over an injected seam store under the zero Scope — used by tests (filestore in a temp dir) and single-tenant callers. This is the seam in action: the manager logic is identical regardless of backend.
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 persists it through the seam.
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.
Persistence runs through the seam (design §5): three seam stores (budgets, allocations, reallocations), each fronted by an in-memory map. Per-record storage (rather than three big JSON files rewritten wholesale) is what makes shared state safe across Prism and prp (§4).
func NewBudgetManager ¶ added in v0.5.10
func NewBudgetManager() (*BudgetManager, error)
NewBudgetManager creates a new budget manager
func NewBudgetManagerForScope ¶ added in v0.36.0
func NewBudgetManagerForScope( budgetStore seam.Store[types.Budget], allocationStore seam.Store[types.ProjectBudgetAllocation], reallocationStore seam.Store[ReallocationRecord], scope seam.Scope, ) (*BudgetManager, error)
NewBudgetManagerForScope builds a BudgetManager over injected seam stores scoped to a Principal — the cloud/multi-tenant entry point. Records partition by scope; all method logic is unchanged.
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
func (bm *BudgetManager) CreateAllocation(ctx context.Context, req *CreateAllocationRequest) (*types.ProjectBudgetAllocation, error)
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) 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
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
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.
Persistence runs through the seam (design §5): an in-memory map fronts a seam.Store[types.Project] of per-project records. Per-project records (rather than one big projects.json) are what make shared state safe — prp (web) and Prism (desktop) editing different projects don't clobber each other's writes (design §4).
func NewManagerForScope ¶ added in v0.36.0
func NewManagerForScope(store seam.Store[types.Project], scope seam.Scope, budgetTracker *BudgetTracker) (*Manager, error)
NewManagerForScope builds a Manager over an injected store scoped to a Principal — the cloud/multi-tenant entry point. Records partition by scope; the method logic is unchanged.
func NewManagerWithStore ¶ added in v0.36.0
func NewManagerWithStore(store seam.Store[types.Project], budgetTracker *BudgetTracker) (*Manager, error)
NewManagerWithStore builds a Manager over an injected seam store under the zero Scope — used by tests (filestore in a temp dir) and single-tenant callers.
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 ¶
AllowLaunches allows new instance launches for a project (clears launch prevention)
func (*Manager) CheckBudgetStatus ¶
CheckBudgetStatus checks the current budget status and triggers alerts if needed
func (*Manager) CheckGrantPeriods ¶ added in v0.12.0
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
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
ClearDefaultAllocation clears the default funding allocation for a project (v0.5.10+)
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
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
DeleteGrantPeriod removes the grant period from a project.
func (*Manager) DeleteOnboardingTemplate ¶ added in v0.12.0
DeleteOnboardingTemplate removes an onboarding template by name or ID.
func (*Manager) DeleteProject ¶
DeleteProject removes a project and all associated data
func (*Manager) DisableProjectBudget ¶
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 ¶
GetProject retrieves a project by ID
func (*Manager) GetProjectByName ¶
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
GetRoleQuotas returns the role quotas for a project's budget.
func (*Manager) IsLaunchPrevented ¶
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 ¶
PreventLaunches prevents new instance launches for a project
func (*Manager) PruneExpiredMembers ¶ added in v0.12.0
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 ¶
RemoveProjectMember removes a member from a project
func (*Manager) SetActiveInstancesFunc ¶ added in v0.29.1
SetActiveInstancesFunc registers a callback used by DeleteProject to check whether any running instances belong to the given project. The daemon wires this up against the state manager so the project manager does not need a direct dependency on pkg/state.
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
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
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