 131868bdca
			
		
	
	131868bdca
	
	
	
		
			
			Major security, observability, and configuration improvements:
## Security Hardening
- Implemented configurable CORS (no more wildcards)
- Added comprehensive auth middleware for admin endpoints
- Enhanced webhook HMAC validation
- Added input validation and rate limiting
- Security headers and CSP policies
## Configuration Management
- Made N8N webhook URL configurable (WHOOSH_N8N_BASE_URL)
- Replaced all hardcoded endpoints with environment variables
- Added feature flags for LLM vs heuristic composition
- Gitea fetch hardening with EAGER_FILTER and FULL_RESCAN options
## API Completeness
- Implemented GetCouncilComposition function
- Added GET /api/v1/councils/{id} endpoint
- Council artifacts API (POST/GET /api/v1/councils/{id}/artifacts)
- /admin/health/details endpoint with component status
- Database lookup for repository URLs (no hardcoded fallbacks)
## Observability & Performance
- Added OpenTelemetry distributed tracing with goal/pulse correlation
- Performance optimization database indexes
- Comprehensive health monitoring
- Enhanced logging and error handling
## Infrastructure
- Production-ready P2P discovery (replaces mock implementation)
- Removed unused Redis configuration
- Enhanced Docker Swarm integration
- Added migration files for performance indexes
## Code Quality
- Comprehensive input validation
- Graceful error handling and failsafe fallbacks
- Backwards compatibility maintained
- Following security best practices
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
		
	
		
			
				
	
	
		
			124 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package units
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // Ulimit is a human friendly version of Rlimit.
 | |
| type Ulimit struct {
 | |
| 	Name string
 | |
| 	Hard int64
 | |
| 	Soft int64
 | |
| }
 | |
| 
 | |
| // Rlimit specifies the resource limits, such as max open files.
 | |
| type Rlimit struct {
 | |
| 	Type int    `json:"type,omitempty"`
 | |
| 	Hard uint64 `json:"hard,omitempty"`
 | |
| 	Soft uint64 `json:"soft,omitempty"`
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	// magic numbers for making the syscall
 | |
| 	// some of these are defined in the syscall package, but not all.
 | |
| 	// Also since Windows client doesn't get access to the syscall package, need to
 | |
| 	//	define these here
 | |
| 	rlimitAs         = 9
 | |
| 	rlimitCore       = 4
 | |
| 	rlimitCPU        = 0
 | |
| 	rlimitData       = 2
 | |
| 	rlimitFsize      = 1
 | |
| 	rlimitLocks      = 10
 | |
| 	rlimitMemlock    = 8
 | |
| 	rlimitMsgqueue   = 12
 | |
| 	rlimitNice       = 13
 | |
| 	rlimitNofile     = 7
 | |
| 	rlimitNproc      = 6
 | |
| 	rlimitRss        = 5
 | |
| 	rlimitRtprio     = 14
 | |
| 	rlimitRttime     = 15
 | |
| 	rlimitSigpending = 11
 | |
| 	rlimitStack      = 3
 | |
| )
 | |
| 
 | |
| var ulimitNameMapping = map[string]int{
 | |
| 	//"as":         rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
 | |
| 	"core":       rlimitCore,
 | |
| 	"cpu":        rlimitCPU,
 | |
| 	"data":       rlimitData,
 | |
| 	"fsize":      rlimitFsize,
 | |
| 	"locks":      rlimitLocks,
 | |
| 	"memlock":    rlimitMemlock,
 | |
| 	"msgqueue":   rlimitMsgqueue,
 | |
| 	"nice":       rlimitNice,
 | |
| 	"nofile":     rlimitNofile,
 | |
| 	"nproc":      rlimitNproc,
 | |
| 	"rss":        rlimitRss,
 | |
| 	"rtprio":     rlimitRtprio,
 | |
| 	"rttime":     rlimitRttime,
 | |
| 	"sigpending": rlimitSigpending,
 | |
| 	"stack":      rlimitStack,
 | |
| }
 | |
| 
 | |
| // ParseUlimit parses and returns a Ulimit from the specified string.
 | |
| func ParseUlimit(val string) (*Ulimit, error) {
 | |
| 	parts := strings.SplitN(val, "=", 2)
 | |
| 	if len(parts) != 2 {
 | |
| 		return nil, fmt.Errorf("invalid ulimit argument: %s", val)
 | |
| 	}
 | |
| 
 | |
| 	if _, exists := ulimitNameMapping[parts[0]]; !exists {
 | |
| 		return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
 | |
| 	}
 | |
| 
 | |
| 	var (
 | |
| 		soft int64
 | |
| 		hard = &soft // default to soft in case no hard was set
 | |
| 		temp int64
 | |
| 		err  error
 | |
| 	)
 | |
| 	switch limitVals := strings.Split(parts[1], ":"); len(limitVals) {
 | |
| 	case 2:
 | |
| 		temp, err = strconv.ParseInt(limitVals[1], 10, 64)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		hard = &temp
 | |
| 		fallthrough
 | |
| 	case 1:
 | |
| 		soft, err = strconv.ParseInt(limitVals[0], 10, 64)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
 | |
| 	}
 | |
| 
 | |
| 	if *hard != -1 {
 | |
| 		if soft == -1 {
 | |
| 			return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: soft: -1 (unlimited), hard: %d", *hard)
 | |
| 		}
 | |
| 		if soft > *hard {
 | |
| 			return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, *hard)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil
 | |
| }
 | |
| 
 | |
| // GetRlimit returns the RLimit corresponding to Ulimit.
 | |
| func (u *Ulimit) GetRlimit() (*Rlimit, error) {
 | |
| 	t, exists := ulimitNameMapping[u.Name]
 | |
| 	if !exists {
 | |
| 		return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
 | |
| 	}
 | |
| 
 | |
| 	return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
 | |
| }
 | |
| 
 | |
| func (u *Ulimit) String() string {
 | |
| 	return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
 | |
| }
 |