All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 34s
CI / test-python-backend-compliance (push) Successful in 28s
CI / test-python-document-crawler (push) Successful in 24s
CI / test-python-dsms-gateway (push) Successful in 17s
Implements the 4-level GCI scoring model (Module -> Risk-Weighted -> Regulation Area -> Final GCI) with DSGVO, NIS2, ISO 27001, and EU AI Act integration. Backend: - 9 Go files: engine, models, weights, validity, NIS2 roles/scoring, ISO mapping/gap-analysis, mock data - GCI handlers with 13 API endpoints under /sdk/v1/gci/ - Routes registered in main.go Frontend: - TypeScript types, API client, Next.js API proxy - Dashboard page with 6 tabs (Overview, Breakdown, NIS2, ISO 27001, Matrix, Audit Trail) - Sidebar navigation entry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
package gci
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
// GracePeriodDays is the number of days after expiry during which
|
|
// the certificate still contributes (with declining factor)
|
|
GracePeriodDays = 180
|
|
|
|
// DecayStartDays is how many days before expiry the linear decay begins
|
|
DecayStartDays = 180
|
|
)
|
|
|
|
// CalculateValidityFactor computes the validity factor for a certificate
|
|
// based on its expiry date.
|
|
//
|
|
// Rules:
|
|
// - Certificate not yet expiring (>6 months): factor = 1.0
|
|
// - Certificate expiring within 6 months: linear decay from 1.0 to 0.5
|
|
// - Certificate expired: linear decay from 0.5 to 0.0 over grace period
|
|
// - Certificate expired beyond grace period: factor = 0.0
|
|
func CalculateValidityFactor(validUntil time.Time, now time.Time) float64 {
|
|
daysUntilExpiry := validUntil.Sub(now).Hours() / 24.0
|
|
|
|
if daysUntilExpiry > float64(DecayStartDays) {
|
|
// Not yet in decay window
|
|
return 1.0
|
|
}
|
|
|
|
if daysUntilExpiry > 0 {
|
|
// In pre-expiry decay window: linear from 1.0 to 0.5
|
|
fraction := daysUntilExpiry / float64(DecayStartDays)
|
|
return 0.5 + 0.5*fraction
|
|
}
|
|
|
|
// Certificate is expired
|
|
daysExpired := -daysUntilExpiry
|
|
if daysExpired > float64(GracePeriodDays) {
|
|
return 0.0
|
|
}
|
|
|
|
// In grace period: linear from 0.5 to 0.0
|
|
fraction := 1.0 - (daysExpired / float64(GracePeriodDays))
|
|
return math.Max(0, 0.5*fraction)
|
|
}
|
|
|
|
// IsExpired returns true if the certificate is past its validity date
|
|
func IsExpired(validUntil time.Time, now time.Time) bool {
|
|
return now.After(validUntil)
|
|
}
|
|
|
|
// IsExpiringSoon returns true if the certificate expires within the decay window
|
|
func IsExpiringSoon(validUntil time.Time, now time.Time) bool {
|
|
daysUntil := validUntil.Sub(now).Hours() / 24.0
|
|
return daysUntil > 0 && daysUntil <= float64(DecayStartDays)
|
|
}
|